Загрузка нескольких файлов в один запрос с использованием модуля запросов python

Модуль запросов Python предоставляет хорошую документацию о том, как загрузить один файл по одному запросу:

 files = {'file': open('report.xls', 'rb')}

Я попытался расширить этот пример, используя этот код, пытаясь загрузить несколько файлов:

 files = {'file': [open('report.xls', 'rb'), open('report2.xls, 'rb')]}

но это привело к этой ошибке:

 File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py",      line 1052, in splittype
 match = _typeprog.match(url)
 TypeError: expected string or buffer

Можно ли загрузить список файлов в одном запросе с помощью этого модуля и как?

Ответы

Ответ 1

Чтобы загрузить список файлов с одним и тем же ключевым значением в одном запросе, вы можете создать список кортежей с первым элементом в каждом кортеже в качестве значения ключа и файлового объекта как второго:

files = [('file', open('report.xls', 'rb')), ('file', open('report2.xls', 'rb'))]

Ответ 2

Несколько файлов с различными значениями ключа могут быть загружены путем добавления нескольких записей в словаре:

files = {'file1': open('report.xls', 'rb'), 'file2': open('otherthing.txt', 'rb')}
r = requests.post('http://httpbin.org/post', files=files)

Ответ 3

Документация содержит четкий ответ.

Цитируется:

Вы можете отправить несколько файлов по одному запросу. Например, предположим, что вы хотите загрузить файлы изображений в HTML-форму с несколькими файлами "Изображения:

К сделайте это, просто установите файлы в список кортежей (form_field_name, file_info):

url = 'http://httpbin.org/post'
multiple_files = [('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
                      ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
r = requests.post(url, files=multiple_files)
r.text

# {
#  ...
#  'files': {'images': 'data:image/png;base64,iVBORw ....'}
#  'Content-Type': 'multipart/form-data; boundary=3131623adb2043caaeb5538cc7aa0b3a',
#  ...
# }

Ответ 4

Вам необходимо создать список файлов для загрузки нескольких изображений:

file_list = [  
       ('Key_here', ('file_name1.jpg', open('file_path1.jpg', 'rb'), 'image/png')),
       ('key_here', ('file_name2.jpg', open('file_path2.jpg', 'rb'), 'image/png'))
   ]

r = requests.post(url, files=file_list)

Если вы хотите отправлять файлы по одному и тому же ключу, вам нужно сохранить ключ одинаковым для каждого элемента, а для другого ключа просто измените ключи.

Источник: https://stackabuse.com/the-python-requests-module/

Ответ 5

Я немного сбит с толку, но непосредственное открытие файла в запросе (однако то же самое написано в официальном руководстве запросов) не так "безопасно".

Просто попробуй:

import os
import requests
file_path = "/home/user_folder/somefile.txt"
files = {'somefile': open(file_path, 'rb')}
r = requests.post('http://httpbin.org/post', files=files)

Да, все будет хорошо, но:

os.rename(file_path, file_path)

И вы получите:

PermissionError:The process cannot access the file because it is being used by another process

Пожалуйста, поправьте меня, если я не прав, но кажется, что файл все еще открыт, и я не знаю, как его закрыть.

Вместо этого я использую:

import os
import requests
#let it be folder with files to upload
folder = "/home/user_folder/"
#dict for files
upload_list = []
for files in os.listdir(folder):
    with open("{folder}{name}".format(folder=folder, name=files), "rb") as data:
        upload_list.append(files, data.read())
r = request.post("https://httpbin.org/post", files=upload_list)
#trying to rename uploaded files now
for files in os.listdir(folder):
    os.rename("{folder}{name}".format(folder=folder, name=files), "{folder}{name}".format(folder=folder, name=files))

Теперь мы не получаем ошибок, поэтому я рекомендую использовать этот способ для загрузки нескольких файлов, иначе вы можете получить некоторые ошибки. Надеюсь, что этот ответ поможет кому-нибудь и сэкономит бесценное время.

Ответ 6

Если у вас есть несколько файлов в списке Python, вы можете использовать eval() в качестве понимания для циклического перебора файлов в параметре файлов записей запросов.

file_list = ['001.jpg', '002.jpg', '003.jpg']
files=[eval(f'("inline", open("{file}", "rb"))') for file in file_list ]

requests.post(
        url=url,
        files=files
)