Empty response with code 400 during file upload
AnsweredHi
I'm trying for the first time to upload a file through the https://upload.box.com/api/2.0/files/content endpoint and I receive the error code 400 but unlike other times that I've received this error code in other situations there is no detailed error description, the response body is empty.
So here's a postman echo of my request to the endpoint and everything seems in accordance to the request expected from me in the API reference:
{
"args":{},
"data":{},
"files":{},
"form":{
"attributes":"{\"name\":\"test.txt\",\"parent\":{\"id\":\"0\"}}",
"file":"abcabcabcabc"
},
"headers":{
"x-forwarded-proto":"https",
"host":"postman-echo.com",
"content-length":"333",
"accept":"application/json",
"authorization":"Bearer -my-access-token-",
"content-type":"multipart/form-data; boundary=8852ffe181cba29a5d03262026ad7e34db1ebed6",
"user-agent":"GuzzleHttp/6.3.3 curl/7.51.0 PHP/7.1.1",
"x-forwarded-port":"443"
},
"json":null,
"url":"https://postman-echo.com/post"
}
-
Hey !
That blank 400 occurs when there's a formatting error with the call. In this specific scenario, the formatting error comes from the way your request is sending the file. It looks like however you're attaching the file isn't sending it as actual "content". How are you building your request? Are you building it all manually (down to each part of the form-data) or are you using an SDK?
As an example, here's a postman echo of how it should look:
{ "args": {}, "data": {}, "files": { "ddd": "data:application/octet-stream;base64,AAAAAAA....this continues for a while .... AAAA=" }, "form": { "attributes": "{\"name\":\"ddd\", \"parent\": {\"id\": \"0\"}}" }, "headers": { "x-forwarded-proto": "https", "host": "postman-echo.com", "content-length": "5482", "accept": "*/*", "accept-encoding": "gzip, deflate", "authorization": "Bearer TOKEN", "cache-control": "no-cache", "content-type": "multipart/form-data; boundary=--------------------------048139954063852910691081", "cookie": "sails.sid=s%3AG9bV5yufyjQAFArtakZYwUiF6ouiEZcO.GGMSMm9ei%2BCAtBtqyzbQ7B2QtCB2ZN2UteWsSRKifcg", "postman-token": "853859a1-b4dd-4903-a9ac-6f68c86a4369", "user-agent": "PostmanRuntime/7.4.0", "x-forwarded-port": "443" }, "json": null, "url": "https://postman-echo.com/post" }
I don't know much about how postman echo displays content, but what I see is that the content ends up in the "files" attribute.
One other thing you can try is using the Box Postman Collection:
https://developer.box.com/docs/box-postman-collection
To get a working API call outside of your code, and then use the "Code" button within postman to generate a quick code snippet. Here's an example of a PHP snippet generated from postman for my API call:setUrl('https://postman-echo.com/post'); $request->setMethod(HTTP_METH_POST); $request->setHeaders(array( 'Postman-Token' => 'db205ef8-114c-44ab-a82d-a38435580ffd', 'cache-control' => 'no-cache', 'Authorization' => 'Bearer TOKEN', 'content-type' => 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' )); $request->setBody('------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="attributes" {"name":"ddd", "parent": {"id": "0"}} ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="ddd" Content-Type: false ------WebKitFormBoundary7MA4YWxkTrZu0gW--'); try { $response = $request->send(); echo $response->getBody(); } catch (HttpException $ex) { echo $ex; }
-
Yes I'm building it manually using Guzzle, I think the critical difference between our requests is that I'm sending the file contents as a regular part of the form-data and yours is recognized as a special kind of file part. It's probably in the specification of the multipart encoding or in the Guzzle documentation so I'll figure it out from here, thanks!
-
So for anyone with similar problems, the solution in Guzzle is to give a file handle instead of a string as the contents field of your multipart param. The file handle will read the contents of the file and correctly encode it into a multipart file. Another option is to do the encoding yourself and pass the encoded content string.
$guzzle->request('POST','https://upload.box.com/api/2.0/files/content', [ "headers" => $headers, "multipart" => [ [ "name" => "attributes", "contents" => $attributes ], [ "name" => "file", "contents" => fopen("/path/to/file.txt", 'r') ] ]);
Please sign in to leave a comment.
Comments
3 comments