cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jbaldwin33
New Member

Canvas Uploading files via POST error 400 "No file uploaded"

Hello! I have been following the Canvas Uploading Files guide to upload a file using an HTTP POST request, however when I make the multipart/form-data request I receive the 400 error code in the response saying "No file uploaded". I feel like I'm just missing a small detail, but I have made sure to add the file parameter after the upload_params received from the response. I am trying to upload a local file but I am unsure of the syntax. my request is formatted as follows:

name=filename.txt&content_type=text/plain&file=@C:\\Users\\User\\Documents\\filename.txt

Am I doing something wrong? I can add more of my code if needed

Labels (3)
0 Kudos
7 Replies
bbennett2
Community Champion

More code would be helpful, mainly because it's a two step process where you make a POST request and then use the response to actually perform the upload. With just a query string, it's hard to say where the issue is happening.

0 Kudos

Of course. For background I'm using LSL (Linden Scripting Language) for use with the Second Life game simulator.

I create the initial request with the following method:

llHTTPRequest(url, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], "name=testfile.txt&size=15&content_type=text/plain&parent_folder_id=1552735&Authorization=authKey")

where "url" is the files folder in my Canvas account I want to upload a file to. When I receive the http response I parse the json string to get the parameters I need which are the response url, and then the upload_params which consist of the filename and the content type:

string responseUrl = llJsonGetValue(response, "upload_url");
string filename = llJsonGetValue(response, ["upload_params", "filename"]);
string contentType = llJsonGetValue(response, ["upload_params", "content_type"]);

and then I make the second request to actually upload the file using the response url, while appending the file parameter to the end of the request. I then make the post request as a multipart/for-data with an arbitrary boundary:

string secondRequest = "name=" + filename + "&content_type=" + contentType + "&file=@C:\\Users\\User\\Documents\\testfile.txt";

llHTTPRequest(responseUrl, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "multipart/form-data;boundary=--123123--"], secondRequest);

after making the second request I get a response with a status of 400 and the json {"error", "No file uploaded"}

0 Kudos
bbennett2
Community Champion

And you're sure that the `upload_params` object is copied in its entirety? The docs make this note:

IMPORTANT: The request is signed, and will be denied if any parameters from the upload_params response are added, removed or modified. The parameters in upload_params may vary over time, and between Canvas installs. It's important for the application to copy over all of the parameters, and not rely on the names or values of the params for any functionality.

Your example follows the documented example, but because it's a 400 bad request error, it seems like your second call is missing something from the initial response.

0 Kudos
jbaldwin33
New Member

Yes, in the upload_params object there are only two parameters, the filename and the content_type, and I grab those directly out of the response. the example in the docs mentions a "key" object but I don't get that in the response. also the authorization key is not required for the second request right? another thing I wasn't sure about the my use of backslashes vs. forward slashes, and I wasn't sure if the @ symbol was necessary.

0 Kudos
bbennett2
Community Champion

I would start by making your second request only the params returned by the first to see if that's the issue. URLs for the web are forward slashes, but if you're on a Windows machine, you may need to use backwards for file locations. 

0 Kudos

I am only using the params returned by the first request. Do I have to worry about any headers that might have been returned by the first request? I know for instance .NET handles some of these things in wrapper classes which may or may not be the case for all languages

0 Kudos
bbennett2
Community Champion

I don't think so. The docs say just to POST to the returned URL without sending the auth key again. Plus, you're getting some kind of response. If it had to do with authorization, it'd be more likely to be a 401 (not authorized) rather than 400 - bad request.

0 Kudos