Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Curl how to POST multipart/form-data data and How to Read multipart/form-data in flask request

I tried posting multipart/form-data through CURL which contains,

  • A JSON Object
  • Stream object pdf and jpeg file
  curl -i -X POST -H  
"Authorization":"eyJhbGciOiJIUzI1NiIsImV4cCI6MTQyNjcwNTY4NiwiaWF0IjoxNDI2NzAyMDg2fQ.eyJpZCI6MTc3fQ.yBwLFez2RnxTojLniL8YLItWVvBb90HF_yfhcsyg3lY" -H    

"Content-Type:application/multipart/form-data" -d '{"user data":  {"preferred_city":"Newyork","within_radious":"5"}}' --data-binary   

"uploaded_documents":@mydocument.pdf http://127.0.0.1:5000/api/city

Now, i need to read this multipart data in flask request object.i tried

request.data

It did print the data but i am not sure how to read the stream object and store the file to disk.

like image 960
Satish Avatar asked Mar 24 '15 11:03

Satish


People also ask

How do you read a multipart form data in python flask?

Installing Flask We create a / route for rendering the index. html template that will display a form and /handle_form route that will process the multipart form, get the uploaded file from the requests. files[] array and return. We'll use this method to send the form to the django server using the requests library.

How do you post a multipart data?

A multipart formpost is what an HTTP client sends when an HTML form is submitted with enctype set to "multipart/form-data". It is an HTTP POST request sent with the request body specially formatted as a series of "parts", separated with MIME boundaries.

How do I post form data using Curl?

To post form data to the server using Curl, you can use one of two command line options: -F (--form) or -d (--data). The -F command-line parameter sends form data with the multipart/form-data content type, and the -d command-line parameter sends form data with the application/x-www-form-urlencoded content type.

How is multipart form data sent?

In multipart, each of the field to be sent has its content type, file name and data separated by boundary from other field. No encoding of the data is necessary, because of the unique boundary. The binary data is sent as it is. The server reads the until the next boundary string.


1 Answers

There are a few problems with your curl command, all of which might contribute to the problem:

  1. application/multipart/form-data is not a valid MIME type, so the Content-Type is invalid. For file uploads the content type would usually be multipart/form-data. Also, you don't need to specify the content type, curl will work it out based on the arguments.
  2. Using -F instead of -d will cause curl to generate and post a multipart/form-data form with a valid boundary.
  3. A name should be specified for each form field.

Putting that together results in this curl command:

curl -i -H "Authorization":"eyJhbGciOiJIUzI1NiIsImV4cCI6MTQyNjcwNTY4NiwiaWF0IjoxNDI2NzAyMDg2fQ.eyJpZCI6MTc3fQ.yBwLFez2RnxTojLniL8YLItWVvBb90HF_yfhcsyg3lY" \
    -F user_data='{"user data": {"preferred_city":"Newyork","within_radious":"5"}}' \
    -F [email protected] \
    http://127.0.0.1:5000/api/city

You can specify the content type for each part if you don't like the ones selected by curl (the file will be application/octet-stream):

curl -i -H "Authorization":"eyJhbGciOiJIUzI1NiIsImV4cCI6MTQyNjcwNTY4NiwiaWF0IjoxNDI2NzAyMDg2fQ.eyJpZCI6MTc3fQ.yBwLFez2RnxTojLniL8YLItWVvBb90HF_yfhcsyg3lY" \
    -F 'user_data={"user data": {"preferred_city":"Newyork","within_radious":"5"}};type=application/json' \
    -F '[email protected];type=application/pdf' \
    http://127.0.0.1:5000/api/city

The last command would generate a HTTP request like this:

POST /api/city HTTP/1.1
User-Agent: curl/7.32.0
Host: 127.0.0.1:5000
Accept: */*
Authorization:eyJhbGciOiJIUzI1NiIsImV4cCI6MTQyNjcwNTY4NiwiaWF0IjoxNDI2NzAyMDg2fQ.eyJpZCI6MTc3fQ.yBwLFez2RnxTojLniL8YLItWVvBb90HF_yfhcsyg3lY
Content-Length: 496
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------1ab997efff76fe66

--------------------------1ab997efff76fe66
Content-Disposition: form-data; name="user_data"
Content-Type: application/json

{"user data": {"preferred_city":"Newyork","within_radious":"5"}}
--------------------------1ab997efff76fe66
Content-Disposition: form-data; name="uploaded_documents"; filename="mydocument.pdf"
Content-Type: application/pdf

this is the mydocument.pdf file.
it should be a pdf file, but this is easier to test with.

--------------------------1ab997efff76fe66--

Then in Flask you can access the form data using request.form, e.g. request.form['user_data']. As it is a json string, you could load it using json.loads(request.form['user_data']).

The uploaded file can be accessed by using request.file as described here and here in the Flask documentation.

like image 76
mhawke Avatar answered Sep 18 '22 18:09

mhawke