Python requests post multipart form data

Как сделать multipart/form-data запрос в python через requests?

Помогите допилить запрос.
Есть api одной закрытой конторы, вот что они пишут:

Запрос:
Тип: POST
Адрес: %Url%/api/app_wrap
Headers:
A2a-auth-token: %TOKEN_KEY%
Content-type: multipart/form-data

POST параметры:
file*, которое содержит апк файл,
params* в котором содержится json объект с параметрами врапа

TOKEN_Key и url у меня есть.

1) что значит маска в suffix?
2) я так понял токен нужно передавать в хедере?
3) контент тайп нужно указывать multipart/form-data ?
4) как пройти валидацию? (или достаточно расширения .apk)
5) сам запрос с передачей файла делаю следующим образом:

head.update( ) wrap_url = 'URL/api/app_wrap/' fname = 'Gone in 60 Seconds APK v 1.3.apk' fpath='D:\\'+fname fpath=open(fpath,'rb') #fpath = fpath.read() #делал и с чтением; на другом сайте через read() заливается file = #делал и просто file = datasend= < 'params' : < 'appId' : '75595', 'build' : 'Play', 'suffix' : 'game.0706', 'isSoftLaunch': 'false', 'isDeviceAdmin': 'false', 'deviceAdminText' : 'test' >> send_apk = requests.post(wrap_url, headers=head, data = datasend, files = file) #делал и вместо datasend просто params с соответствующим изменением кода выше

Без самого сайта конечно сложно что подсказать, но сама логика запроса как вам?
Поддержка не особо разговорчива, написала только что неправильно формирую запрос.

Источник

Python requests post multipart form data

Last updated: Jun 15, 2023
Reading time · 5 min

banner

# Table of Contents

# Python: Sending multipart/form-data request with requests

To send a «multipart/form-data» request with the requests library in Python:

  1. Specify the files parameter as a dictionary when calling requests.post()
  2. When the files parameter is set, requests sends a multipart/form-data POST request instead of a application/x-www-form-urlencoded POST request.
Copied!
from pprint import pprint import requests url = 'https://httpbin.org/post' response = requests.post( url, files='id': 1, 'site': 'bobbyhadz.com'>, timeout=30 ) print(response.status_code) pprint(response.json()['headers'])

As shown in the code sample, the files parameter doesn’t have to contain files.

However, the files parameter has to be used even if you don’t need to upload files to the server.

Make sure you have the requests library installed to be able to run the code snippet.

Copied!
pip install requests # or with pip3 pip3 install requests

send multipart form data request without files

Note that the httpbin API is a bit flaky, so the HTTP request might time out depending on the time of the day.

When the files parameter is specified in the call to request.post() , then the requests library sets the Content-Type header to multipart/form-data in the POST request.

You can access the request headers as response.json()[‘headers’] to verify that the Content-Type header is set to multipart/form-data .

Copied!
from pprint import pprint # . print(response.status_code) pprint(response.json()['headers'])

The output will look something like this:

Copied!
200 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '252', 'Content-Type': 'multipart/form-data; ' 'boundary=344105e37bee4840291f830328272d08', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.28.2', 'X-Amzn-Trace-Id': 'Root=1-648b1179-6d365c68138be548314b79a0' >

When making multipart/form-data HTTP requests, make sure you aren’t setting the Content-Type header yourself.

The requests library will automatically set the Content-Type header correctly and it will include the boundary parameter as shown in the code sample above.

The boundary parameter needs to match the boundary that is used in the request body, so it has to be automatically set by requests .

The same approach can be used if you need to send a file over the network.

Copied!
import requests url = 'https://httpbin.org/post' files = 'file': open('data.json', 'rb')> response = requests.post(url, files=files, timeout=30) print(response.text) print(response.status_code)

The example assumes that you have a data.json file in the same directory as your Python script.

Copied!
"id": 1, "name": "bobby hadz", "site": "bobbyhadz.com", "topic": "Python" >

send multipart form data request with requests in python

# Setting the filename, Content-Type and Headers explicitly

You can set the filename, Content-Type and headers explicitly by using a tuple for the dictionary value.

Copied!
import requests url = 'https://httpbin.org/post' files = 'file': ( 'example.xlsx', open('example.xlsx', 'rb'), 'application/vnd.ms-excel', 'Expires': '0'> ) > response = requests.post(url, files=files, timeout=30) print(response.text) print(response.status_code)

The code sample assumes that you have an example.xlsx file in the same directory as your Python main.py script.

explicitly specifying filename content type headers

The tuple we passed for the file dictionary key contains 4 elements:

  1. The name of the file.
  2. The data to send over the network.
  3. The Content-Type.
  4. The headers.

In other words, the tuple has the following format: (filename, data, Content-Type, headers) .

If the dictionary value is a simple string, the filename will be the same as the dictionary key.

Copied!
import requests url = 'https://httpbin.org/post' files = 'session_id': '192ZXJAWKjewiqe1j23XXA2h3' > response = requests.post(url, files=files, timeout=30) print(response.text) print(response.status_code)

Running the code sample will produce output similar to this:

Copied!
"args": >, "data": "", "files": "session_id": "192ZXJAWKjewiqe1j23XXA2h3" >, "form": >, "headers": "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "177", "Content-Type": "multipart/form-data; boundary=ff9ca52fa6489578695603d655e51c7b", "Host": "httpbin.org", "User-Agent": "python-requests/2.28.2", "X-Amzn-Trace-Id": "Root=1-648b17bf-5cc0e58b1dce855345d7ceb6" >, "json": null, "origin": "109.120.245.4", "url": "https://httpbin.org/post" >

filename same as dictionary key

The files property is set to the specified session_id .

If the dictionary value is a tuple and the first item is None , the filename property will not be included.

Copied!
import requests url = 'https://httpbin.org/post' files = 'session_id': (None, '192ZXJAWKjewiqe1j23XXA2h3') > response = requests.post(url, files=files, timeout=30) print(response.text) print(response.status_code)

Running the code sample above produces the following output.

Copied!
"args": >, "data": "", "files": >, "form": "session_id": "192ZXJAWKjewiqe1j23XXA2h3" >, "headers": "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "154", "Content-Type": "multipart/form-data; boundary=5ae1c6c70e9f9e62a9b6309634aa475f", "Host": "httpbin.org", "User-Agent": "python-requests/2.28.2", "X-Amzn-Trace-Id": "Root=1-648b191d-3bc7da643eb0c7137285fe10" >, "json": null, "origin": "109.120.245.4", "url": "https://httpbin.org/post" >

The files dictionary is empty and the form property is set to the specified session_id .

The first value in the tuple should be None for plain text fields.

Copied!
files = 'session_id': (None, '192ZXJAWKjewiqe1j23XXA2h3') >

The None value serves as a placeholder for the filename field which is only used for file uploads.

When sending text fields, set the first element in the tuple to None .

  • A tuple of 2 elements — (filename, fileobj)
  • A tuple of 3 elements — (filename, fileobj, content_type)
  • A tuple of 4 elements — (filename, fileobj, content_type, custom_headers)

The fileobj element can be an actual file or a string when dealing with plain-text fields.

Here is an example that sets the fileobj element to a string.

Copied!
import requests url = 'https://httpbin.org/post' files = 'file': ( 'example.csv', 'some,data,to,send\nanother,row,to,send\n' ) > response = requests.post(url, files=files, timeout=30) print(response.text) print(response.status_code)

Running the code sample produces the following output.

Copied!
"args": >, "data": "", "files": "file": "some,data,to,send\nanother,row,to,send\n" >, "form": >, "headers": "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "185", "Content-Type": "multipart/form-data; boundary=e01ea5853a69f145728a7aba04d78fdd", "Host": "httpbin.org", "User-Agent": "python-requests/2.28.2", "X-Amzn-Trace-Id": "Root=1-648b1aad-7789258e70d4320e76bf7f82" >, "json": null, "origin": "109.120.245.4", "url": "https://httpbin.org/post" >

The example sends a string that is received as a file.

# Using the requests-toolbelt module to send multipart/form-data

You can also use the requests-toolbelt module when sending multipart/form-data requests.

First, open your terminal in your project’s root directory and install the module.

Copied!
pip install requests-toolbelt # or with pip3 pip3 install requests-toolbelt

Now import and use the module as follows.

Copied!
import requests from requests_toolbelt.multipart.encoder import MultipartEncoder url = 'https://httpbin.org/post' multipart_data = MultipartEncoder( fields= # plain text fields 'field1': 'value1', 'field2': 'value2', # file upload field 'file': ('example.xlsx', open('example.xlsx', 'rb'), 'text/plain') > ) response = requests.post(url, data=multipart_data, headers='Content-Type': multipart_data.content_type>, timeout=30) print(response.text) print(response.status_code)

Running the code sample produces the following output.

Copied!
"args": >, "data": "", "files": "file": "data:text/plain;base64, . REST TRUNCATED" >, "form": "field1": "value1", "field2": "value2" >, "headers": "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "5213", "Content-Type": "multipart/form-data; boundary=3fc36883f949412e8c0986a8d86f25f6", "Host": "httpbin.org", "User-Agent": "python-requests/2.28.2", "X-Amzn-Trace-Id": "Root=1-648b1d21-57f5cc64591f2f8d45db717c" >, "json": null, "origin": "109.120.245.4", "url": "https://httpbin.org/post" > 200

The file is set under files > file and the plain text fields are specified under form .

The requests-toolbelt module enables us to stream multipart form data using the MultipartEncoder class.

You can also use multipart/form-data encoding for requests that don’t require files.

Copied!
import requests from requests_toolbelt.multipart.encoder import MultipartEncoder url = 'https://httpbin.org/post' multipart_data = MultipartEncoder( fields= # plain text fields 'field1': 'value1', 'field2': 'value2', > ) response = requests.post(url, data=multipart_data, headers='Content-Type': multipart_data.content_type>, timeout=30) print(response.text) print(response.status_code)

Running the code sample produces the following output.

Copied!
"args": >, "data": "", "files": >, "form": "field1": "value1", "field2": "value2" >, "headers": "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "224", "Content-Type": "multipart/form-data; boundary=161e261edbca4e3389aac536bc795b16", "Host": "httpbin.org", "User-Agent": "python-requests/2.28.2", "X-Amzn-Trace-Id": "Root=1-648b1e05-3c74b8ed4e5d02ab6ee061a9" >, "json": null, "origin": "109.120.245.4", "url": "https://httpbin.org/post" > 200

We only set plain text fields when issuing the request, so the files object is empty.

You can check out more examples of using the requests-toolbelt module on the package’s GitHub page.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.

Источник

Читайте также:  If then else and java
Оцените статью