Guzzle ~6.0 multipart and form_params

47.9k views Asked by At

I am trying to upload file and send post parameters at the same time like this:

$response = $client->post('http://example.com/api', [
    'form_params' => [
        'name' => 'Example name',
    ],
    'multipart' => [
        [
            'name'     => 'image',
            'contents' => fopen('/path/to/image', 'r')
        ]
    ]
]);

However my form_params fields are ignored and only the multipart fields are present in my post body. Can I send both at all with guzzle 6.0 ?

5

There are 5 answers

1
Simon Crowfoot On BEST ANSWER

I ran into the same problem. You need to add your form_params to the multipart array. Where 'name' is the form element name and 'contents' is the value. The example code you supplied would become:

$response = $client->post('http://example.com/api', [
    'multipart' => [
        [
            'name'     => 'image',
            'contents' => fopen('/path/to/image', 'r')
        ],
        [
            'name'     => 'name',
            'contents' => 'Example name'
        ]
    ]
]);
4
Jordan Dobrev On

I got there too, but unfortunately it does not work if you have multidimensional params array. The only way i got it to work is if you send the form_paramaters as query parameters in the array:

$response = $client->post('http://example.com/api', [
    'query' => [
        'name' => 'Example name',
    ],
    'multipart' => [
        [
            'name'     => 'image',
            'contents' => fopen('/path/to/image', 'r')
        ]
    ]
]);
1
ravi singhal On
    $body['query'] = $request->input();
        if($_FILES)
         {
            $filedata = [];
            foreach( $_FILES as $key => $file){               
                if(!($file['tmp_name'] == '')){
                    $file['filename'] = $file['name'];
                    $file['name']=$key;
                    $file['contents'] = fopen($file['tmp_name'], 'r');
                    $file['headers'] = array('Content-Type' => mime_content_type($file['tmp_name']));
                }
                else{
                    $file['contents'] = '';
                }
                array_push($filedata, $file);
            }
        $body['multipart'] = $filedata;
        }

        $header= ['headers'=>[
                    'User-Agent' => 'vendor/1.0',
                    'Content-Type' =>'multipart/form-data',
                    'Accept'     => 'application/json',
                    'Authorization' => "Authorization: Bearer ".$token,
                ]];
        $client = new Client($header);
        $response = $client->POST($url, $body);
        $response=json_decode($response->getBody());
0
Marcus On

You can send both data and files as in the following code:

$response = $client->post('http://example.com/api', [
    'query' => [
        'name' => 'Example name',
    ],
    'multipart' => [
        [
            'name'     => 'image',
            'contents' => fopen('/path/to/image', 'r')
        ],
        [
            'name'     => 'product',
            'contents' => $product_array
    ]
]);

The product would be in the post part of the request, the files in the files part.

Where it get's tricky is when the contents of the data you are trying to send along with the files are in an array - since you can't just send the array as json when also using multipart. The trick I found to get around this is to json_encode the $product_array and then base64_encode that. Reversing the process on the other end gives you the desired results. Hope that helps.

0
Solo.dmitry On

I googled similar problem and write here advice:

Do not set header "Content-Type" manually for multipart request.