Guzzle ~6.0 multipart and form_params
Asked Answered
D

5

22

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 ?

Dorado answered 4/6, 2015 at 14:3 Comment(0)
L
52

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'
        ]
    ]
]);
Lowney answered 10/6, 2015 at 10:19 Comment(1)
if the code using headers tag, so, headers are written inside the 'multipart' or before multipart? like ``` $response = $client->post('xyz', [ 'headers' => [] 'multipart' => [] ]; or 'multipart' => [ 'name' => 'a' 'contents' => 'b' 'headers => 'c' ] ]Extrasensory
D
7

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')
        ]
    ]
]);
Dorado answered 11/6, 2015 at 12:55 Comment(4)
Were you able to successfully use that mixture of RequestOptions? When I perform that request you have, my query items get sent but the multipart does not.Discovery
According to the maintainer of Guzzle, this cannot work. Multipart cannot be mixed with any other request option. github.com/guzzle/guzzle/issues/1386Discovery
Correction. This should work because query is not a body related option.Discovery
You can have multiple multipart elements with the same name.Boni
M
6

I googled similar problem and write here advice:

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

Mending answered 3/11, 2020 at 10:51 Comment(0)
U
1
    $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());
Uptodate answered 7/8, 2021 at 5:26 Comment(1)
As I find best way to send multiples file and inputs variable in a single query with this Laravel function.Uptodate
D
0

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.

Disannul answered 7/10, 2022 at 17:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.