Upload file using Guzzle 6 to API endpoint

63,750

Solution 1

The way you are POSTing data is wrong, hence received data is malformed.

Guzzle docs:

The value of multipart is an array of associative arrays, each containing the following key value pairs:

name: (string, required) the form field name

contents:(StreamInterface/resource/string, required) The data to use in the form element.

headers: (array) Optional associative array of custom headers to use with the form element.

filename: (string) Optional string to send as the filename in the part.

Using keys out of above list and setting unnecessary headers without separating each field into one array will result in making a bad request.

$res = $client->request('POST', $this->base_api . $endpoint, [
    'auth'      => [ env('API_USERNAME'), env('API_PASSWORD') ],
    'multipart' => [
        [
            'name'     => 'FileContents',
            'contents' => file_get_contents($path . $name),
            'filename' => $name
        ],
        [
            'name'     => 'FileInfo',
            'contents' => json_encode($fileinfo)
        ]
    ],
]);

Solution 2

$body = fopen('/path/to/file', 'r');
$r = $client->request('POST', 'http://httpbin.org/post', ['body' => $body]);

http://docs.guzzlephp.org/en/latest/quickstart.html?highlight=file

Share:
63,750
agucho
Author by

agucho

Web Application Developer, using PHP, CodeIgniter, Laravel, jQuery, html, css, js, Twitter Bootstrap, LESS, MySQL, rsync, git, ExpressionEngine add-on developer

Updated on December 10, 2021

Comments

  • agucho
    agucho over 2 years

    I am able to upload a file to an API endpoint using Postman.

    I am trying to translate that into uploading a file from a form, uploading it using Laravel and posting to the endpoint using Guzzle 6.

    Screenshot of how it looks in Postman (I purposely left out the POST URL) enter image description here

    Below is the text it generates when you click the "Generate Code" link in POSTMAN:

    POST /api/file-submissions HTTP/1.1
    Host: strippedhostname.com
    Authorization: Basic 340r9iu34ontoeioir
    Cache-Control: no-cache
    Postman-Token: 6e0c3123-c07c-ce54-8ba1-0a1a402b53f1
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
    
    ----WebKitFormBoundary7MA4YWxkTrZu0gW
    Content-Disposition: form-data; name="FileContents"; filename=""
    Content-Type: 
    
    
    ----WebKitFormBoundary7MA4YWxkTrZu0gW
    Content-Disposition: form-data; name="FileInfo"
    
    { "name": "_aaaa.txt", "clientNumber": "102425", "type": "Writeoff" }
    ----WebKitFormBoundary7MA4YWxkTrZu0gW
    

    Below is controller function for saving the file and other info. The file uploads correctly, I am able to get the file info.

    I think the problem I am having is setting the multipart and headers array with the correct data.

    public function fileUploadPost(Request $request)
    {
        $data_posted = $request->input();
        $endpoint = "/file-submissions";
        $response = array();
        $file = $request->file('filename');
        $name = time() . '_' . $file->getClientOriginalName();
        $path = base_path() .'/public_html/documents/';
    
        $resource = fopen($file,"r") or die("File upload Problems");
    
        $file->move($path, $name);
    
        // { "name": "test_upload.txt", "clientNumber": "102425", "type": "Writeoff" }
        $fileinfo = array(
            'name'          =>  $name,
            'clientNumber'  =>  "102425",
            'type'          =>  'Writeoff',
        );
    
        $client = new \GuzzleHttp\Client();
    
        $res = $client->request('POST', $this->base_api . $endpoint, [
            'auth' => [env('API_USERNAME'), env('API_PASSWORD')],
            'multipart' => [
                [
                    'name'  =>  $name,
                    'FileContents'  => fopen($path . $name, 'r'),
                    'contents'      => fopen($path . $name, 'r'),
                    'FileInfo'      => json_encode($fileinfo),
                    'headers'       =>  [
                        'Content-Type' => 'text/plain',
                        'Content-Disposition'   => 'form-data; name="FileContents"; filename="'. $name .'"',
                    ],
                    // 'contents' => $resource,
                ]
            ],
        ]);
    
        if($res->getStatusCode() != 200) exit("Something happened, could not retrieve data");
    
        $response = json_decode($res->getBody());
    
        var_dump($response);
        exit();
    }
    

    The error I am receiving, screenshot of how it displays using Laravel's debugging view:

    enter image description here