How to send JSON as part of multipart POST-request
21,814
You are setting the header yourself, including a boundary. Don't do this; requests
generates a boundary for you and sets it in the header, but if you already set the header then the resulting payload and the header will not match. Just drop you headers altogether:
def send_request():
payload = {"param_1": "value_1", "param_2": "value_2"}
files = {
'json': (None, json.dumps(payload), 'application/json'),
'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
}
r = requests.post(url, files=files)
print(r.content)
Note that I also gave the file
part a filename (the base name of the file
path`).
For more information on multi-part POST requests, see the advanced section of the documentation.
Comments
-
Andersson almost 2 years
I have following POST-request form (simplified):
POST /target_page HTTP/1.1 Host: server_IP:8080 Content-Type: multipart/form-data; boundary=AaaBbbCcc --AaaBbbCcc Content-Disposition: form-data; name="json" Content-Type: application/json { "param_1": "value_1", "param_2": "value_2"} --AaaBbbCcc Content-Disposition: form-data; name="file"; filename="..." Content-Type: application/octet-stream <..file data..> --AaaBbbCcc--
I try to send POST-request with
requests
:import requests import json file = "C:\\Path\\To\\File\\file.zip" url = 'http://server_IP:8080/target_page' def send_request(): headers = {'Content-type': 'multipart/form-data; boundary=AaaBbbCcc'} payload = { "param_1": "value_1", "param_2": "value_2"} r = requests.post(url, files={'json': (None, json.dumps(payload), 'application/json'), 'file': (open(file, 'rb'), 'application/octet-stream')}, headers=headers) print(r.content) if __name__ == '__main__': send_request()
but it returns status
400
with following comment:Required request part \'json\' is not present. The request sent by the client was syntactically incorrect.
Please point on my mistake. What should I change to make it work?
-
jsbueno about 8 yearsIf anything the fact the O.P. is passing the boundary pattern inside an opaque string, and still expecting the library to reuse that pattern, should be a goog clue that something is wrong.
-
Khamidulla over 5 yearsUsing this code snippet i was able to send request. However at django backend says
AttributeError: 'WSGIRequest' object has no attribute 'data'
. Do you have any idea why? -
Martijn Pieters over 5 years@Khamidulla: that's not a problem with this code. Something on the Django server has an error, there is no
data
attribute on the Django Request object. -
Khamidulla over 5 years@MartijnPieters I will publish my question and send you link later today. Thank you for you response.
-
Scaramouche about 4 yearshello, is the data supposed to be received via
body
in the server? it's arriving empty, thank you -
Martijn Pieters about 4 years@Scaramouche: yes, POST data (however it is encoded) is sent in the request body. Replace your URL with
https://httpbin.org/post
to receive a JSON response that echoes what you sent to verify that you are sending a valid request; this could be a server-side issue rather than a Requests issue. -
JavaSa almost 3 years@MartijnPieters; how this request would look if I have multiple files with one metadata json?
-
Martijn Pieters almost 3 years@JavaSa: Use a tuple with
(partname, (filename, filedata, content_type))
elements, that way part names don't need to be unique . Do look at the documentation I linked to from my answer, which includes that format.