Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Отправка POST запроса с файлами и metadata


(Dzmitry Ihnatsyeu) #1

Всем привет!
Столкнулся с такой проблемой:
отправляю POST запрос на API используя requests с formdata и файлами в одном запросе.
Пытался делать разными способами:
1)
data = {‘test’:1}
with open(“file.png”, “r+”) as test_file:
requests.post(data = json.dumps(data), files={‘test_file’:test_file)

req_data = {‘name’:‘test_file’, ‘data’:json.dumps(data)}
requests.post(files={‘test_file’:open(‘file.png’), ‘r+’}, data=req_data)

В обоих случаях получаю 500 ошибку.
Возможно кто-то уже сталкивался с подобной задачей и может подсказать решение проблемы.


(rmerkushin) #2

Ну во-первых, режим чтения не r+ должен быть, а rb. Во-вторых, где mime-type? В-третьих, посмотрите оф. доку к либе requests: http://docs.python-requests.org/en/latest/user/advanced/#post-multiple-multipart-encoded-files, http://docs.python-requests.org/en/latest/user/advanced/#streaming-uploads


(Dzmitry Ihnatsyeu) #3
  1. Режим r+ позволяет как записывать файлы, так и читать. Некоторые фрагменты кода записи в файл я опустил т.к. в данном примере они не важны. Поскольку тесты запускаются на unix системах, открытия в бинарном формате не обязательно. Но для чистоты эксперимента файл был открыт в режиме rb однако ошибка по-прежнему воспроизводилась.
  2. при отправке запроса через requests c параметром files автоматически отправляется запрос как multipart/form-data а не application/x-www-form-urlencoded. К тому же это единственный способ отправить mutlipart/form-data запрос через модуль requests.

Таки решение я нашел, возможно кому-то пригодится в будущем. На данным момент единственным вариантом отправки данных формы является файл с указанием типа контекста через tuple (filename, data, content_type, headers).
Например
files = {“approved”: (“approved”, open(‘test.png’, ‘rb’), ‘image/png’),“json”: (‘json_data’, open(“test.json”, “rb”),‘application/json’)}
requets.post(url, files=files)


(rmerkushin) #4

Ну про rb написал т.к. авторы рекомендуют использовать именно его :smile: