Forums

Where to insert "content" keyword when using Form-based File Upload in HTML to communicate with pythonanywhere API API

Hello, I would like to know where and how to insert the "content" keyword or field name in my headers when using the HTML form-based method for uploading a file to the server via the API? The followings are what I am sending to PA server from an Arduino device using the client.println() function from its WiFiClientSecure library.


*POST https://www.pythonanywhere.com/api/v0/user/wee/files/path/home/wee/foo.csv/ HTTP/1.1

Authorization: Token xxxxxxxxxxxxxxxxxxxxxxxxx

Host: www.pythonanywhere.com

User-Agent: Arduino/1.0

Connection: close

Content-Type: multipart/form-data; boundary=content_boundary

Content-Length: 266

--content_boundary

...content of the file sent as a series of char bytes...

--content_boundary--*


The PA server seems to have accepted the above POST request but responded with an error about "You must provide a file with the name 'content'." But I do not know where, the format, and how to insert the required keyword "content" in the headers of my HTML form.


The followings are the responses to the POST request I have received from PA server.


Read Server Response:

Set-Cookie: sessionid=vuor61h0123rzkedzdl5mjh0svnsrheb; expires=Tue, 11 Jan 2022 03:35:39 GMT; HttpOnly; Max-Age

Server: PythonAnywhereSite=None; Secure

headers received.

response: {"detail":"You must provide a file with the name 'content'."}

close connection


Adding the following Content-Disposition after --content_boundary resulted in no response from the server.


Content-Disposition: form-data; name="content"; filename="content.csv"

Content-Type: text/csv

You need to provide content as the name of the file. The asnwer to this SO question has an example that shows where you need to set it.

Hi Glenn, thanks for your reply. I checked out the link to StackOverflow. I am sorry I still don't get it. When you said "You need to provide content as the name of the file" do you mean in my Content-Disposition header after my boundary? Like as shown below? Or the filename of the file to be uploaded have to be named "content"? Or is there a content header in the HTML form I have to include in my header and provide this content header with the name of the file?


Content-Disposition: form-data; name="content";


Now, I know in the python code you can do this (see below). But I struggle to find the equivalent header in HTML form for the field name "files" in the request.post parameters in python.


resp = requests.post(

urljoin(api_base, "files/path/home/{username}/foo.txt".format(username=username)),

files={"content": "hello world"},

headers={"Authorization": "Token {api_token}".format(api_token=api_token)}

)

The easiest way is to use javascript and FormData to upload file from the page.

Thanks fjl. I was able to get it done using python on my RaspPi and computer. But I need to reproduce it for an Arduino IoT device using cpp.

OK -- so essentially you have to write your own HTTP headers "by hand" because there's no library like requests to use there -- is that right?

In that case, the

 Content-Disposition: form-data; name="content";

...on that SO link looks like the right way to do it.

Thanks, giles! Yes, you are right, there is no requests library written for python that I can use in Arduino written in c and cpp. Unfortunately, using


Content-Disposition: form-data; name="content";

did not work out for me. In fact, I did not get any response from the server if I included this line in my headers.


So far this is the nearest api structure that I found which is similar to what Pythonanywhere is using. https://api.slack.com/methods/files.upload


"The content of the file can either be posted using an enctype of multipart/form-data (with the file parameter named file), in the usual way that files are uploaded via the browser, or the content of the file can be sent as a POST var called content. The latter should be used for creating a "file" from a long message/paste and forces "editable" mode."


They also mention something about sending a "POST var called content". The example code that they have is written in curl


curl -F "content=launch plan" -H "Authorization: Bearer xoxb-xxxxxxxxx-xxxx" https://slack.com/api/files.upload

I tried to adapt it using the Form-based method in HTML but I still failed to get a response from the server.