Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload file using Guzzle

Tags:

php

curl

laravel

I have a form where video can be uploaded and sent to remote destination. I have a cURL request which I want to 'translate' to PHP using Guzzle.

So far I have this:

public function upload(Request $request)
    {
        $file     = $request->file('file');
        $fileName = $file->getClientOriginalName();
        $realPath = $file->getRealPath();

        $client   = new Client();
        $response = $client->request('POST', 'http://mydomain.de:8080/spots', [
            'multipart' => [
                [
                    'name'     => 'spotid',
                    'country'  => 'DE',
                    'contents' => file_get_contents($realPath),
                ],
                [
                    'type' => 'video/mp4',
                ],
            ],
        ]);

        dd($response);

    }

This is cURL which I use and want to translate to PHP:

curl -X POST -F 'body={"name":"Test","country":"Deutschland"};type=application/json' -F 'file=@C:\Users\PROD\Downloads\617103.mp4;type= video/mp4 ' http://mydomain.de:8080/spots

So when I upload the video, I want to replace this hardcoded

C:\Users\PROD\Downloads\617103.mp4.

When I run this, I get an error:

Client error: POST http://mydomain.de:8080/spots resulted in a 400 Bad Request response: request body invalid: expecting form value 'body`'

Client error: POST http://mydomain.de/spots resulted in a 400 Bad Request response: request body invalid: expecting form value 'body'

like image 404
harunB10 Avatar asked Oct 12 '17 13:10

harunB10


2 Answers

I'd review the Guzzle's multipart request options. I see two issues:

  1. The JSON data needs to be stringified and passed with the same name you're using in the curl request (it's confusingly named body).
  2. The type in the curl request maps to the header Content-Type. From $ man curl:

    You can also tell curl what Content-Type to use by using 'type='.

Try something like:

$response = $client->request('POST', 'http://mydomain.de:8080/spots', [
    'multipart' => [
        [
            'name'     => 'body',
            'contents' => json_encode(['name' => 'Test', 'country' => 'Deutschland']),
            'headers'  => ['Content-Type' => 'application/json']
        ],
        [
            'name'     => 'file',
            'contents' => fopen('617103.mp4', 'r'),
            'headers'  => ['Content-Type' => 'video/mp4']
        ],
    ],
]);
like image 66
Jacob Budin Avatar answered Oct 06 '22 00:10

Jacob Budin


  • While using the multipart option, make sure you are not passing content-type => application/json :)
  • If you want to POST form fields AND upload file together, just use this multipart option. It's an array of arrays where name is form field name and it's value is the POSTed form value. An example:
'multipart' => [
                [
                    'name' => 'attachments[]', // could also be `file` array
                    'contents' => $attachment->getContent(),
                    'filename' => 'dummy.png',
                ],
                [
                    'name' => 'username',
                    'contents' => $username
                ]
            ]
like image 39
R Sun Avatar answered Oct 05 '22 23:10

R Sun