Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Requests: Post JSON and file in single request

I need to do a API call to upload a file along with a JSON string with details about the file.

I am trying to use the python requests lib to do this:

import requests  info = {     'var1' : 'this',     'var2'  : 'that', }  data = json.dumps({     'token' : auth_token,     'info'  : info, })  headers = {'Content-type': 'multipart/form-data'}  files = {'document': open('file_name.pdf', 'rb')}  r = requests.post(url, files=files, data=data, headers=headers) 

This throws the following error:

    raise ValueError("Data must not be a string.")  ValueError: Data must not be a string 

If I remove the 'files' from the request, it works.
If I remove the 'data' from the request, it works.
If I do not encode data as JSON it works.

For this reason I think the error is to do with sending JSON data and files in the same request.

Any ideas on how to get this working?

like image 441
oznu Avatar asked Oct 18 '13 01:10

oznu


People also ask

How do you pass JSON data in a POST request in Python?

To post a JSON to the server using Python Requests Library, call the requests. post() method and pass the target URL as the first parameter and the JSON data with the json= parameter. The json= parameter takes a dictionary and automatically converts it to a JSON string.

How do you pass a body in a POST request in Python?

You'll want to adapt the data you send in the body of your request to the specified URL. Syntax: requests. post(url, data={key: value}, json={key: value}, headers={key:value}, args) *(data, json, headers parameters are optional.)

Can we send JSON object in POST request?

To post JSON to a REST API endpoint, you must send an HTTP POST request to the REST API server and provide JSON data in the body of the POST message. You also need to specify the data type in the body of the POST message using the Content-Type: application/json request header.

Can you pass JSON in a GET request?

To answer your question, yes you may pass JSON in the URI as part of a GET request (provided you URL-encode).


2 Answers

Don't encode using json.

import requests  info = {     'var1' : 'this',     'var2'  : 'that', }  data = {     'token' : auth_token,     'info'  : info, }  headers = {'Content-type': 'multipart/form-data'}  files = {'document': open('file_name.pdf', 'rb')}  r = requests.post(url, files=files, data=data, headers=headers) 

Note that this may not necessarily be what you want, as it will become another form-data section.

like image 140
proteneer Avatar answered Sep 17 '22 17:09

proteneer


See this thread How to send JSON as part of multipart POST-request

Do not set the Content-type header yourself, leave that to pyrequests to generate

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) 
like image 37
ralf htp Avatar answered Sep 17 '22 17:09

ralf htp