Качване на множество файлове в една заявка с помощта на модул за заявки на 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

Възможно ли е да качите списък с файлове в една заявка с помощта на този модул и как?


person user462455    schedule 12.08.2013    source източник
comment
защо няма приет отговор? Отговорът с висок вот по-долу не е ли достатъчен?   -  person Wade Anderson    schedule 29.10.2014
comment
Пинг/блъскане. Достатъчен ли е някой от тези отговори?   -  person Wayne Werner    schedule 13.05.2016


Отговори (8)


За да качите списък с файлове със същата стойност на ключ в една заявка, можете да създадете списък с кортежи с първия елемент във всеки кортеж като стойност на ключ и файловия обект като втори:

files = [('file', open('report.xls', 'rb')), ('file', open('report2.xls', 'rb'))]
person Ryan Fau    schedule 25.12.2013
comment
Да кажем, че имам списък с имена на файлове, има ли начин да направя това с разбиране на списъка? - person Maciek Semik; 22.03.2019
comment
@MatthewSemik file_names = [abc.txt, pqr.txt ] files = [('file', open(f, 'rb')) за f в file_names] - person Swapnil Suryawanshi; 10.12.2019
comment
Благодаря, работи добре за мен - person Mohit Duklan; 03.06.2021

Множество файлове с различни ключови стойности могат да бъдат качени чрез добавяне на множество речникови записи:

files = {'file1': open('report.xls', 'rb'), 'file2': open('otherthing.txt', 'rb')}
r = requests.post('http://httpbin.org/post', files=files)
person Lukasa    schedule 12.08.2013
comment
интересно Ще опита вашия подход. Причината, поради която опитах списък, беше, че Flask (уеб рамка на python) казва, че файловете са multidict и начинът за достъп до всички качени файлове е да направя: request.files.getall('file') - person user462455; 12.08.2013
comment
Трябва ли сам да затварям файловите дескриптори? или ще бъдат автоматично затворени като с open('file', 'r') as f..? - person kaki gadol; 30.10.2019
comment
@Lukasa, има ли подобен подход на решение в R? - person user5249203; 25.03.2021

документацията съдържа ясен отговор .

Цитирано:

Можете да изпратите няколко файла в една заявка. Да предположим например, че искате да качите файлове с изображения в 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',
#  ...
# }
person Wade Anderson    schedule 29.10.2014
comment
Каква форма може да приеме file_info? Мога ли да пропусна типа съдържание? Какво друго може да бъде част от file_info? документацията не навлиза в подробности. - person A.R.; 29.01.2015
comment
@AmauryRodriguez Препоръчвам ви да погледнете източника за всички тези подробности. - person Wade Anderson; 28.10.2015

Трябва да създадете списък с файлове, за да качите няколко изображения:

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/

person Abdul Haseeb    schedule 23.04.2019

Малко съм объркан, но директното отваряне на файл в заявка (колкото и да е написано в официалното ръководство за заявки) не е толкова "безопасно".

Просто опитай:

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))

Сега не получаваме грешки, така че препоръчвам да използвате този начин за качване на няколко файла или може да получите някои грешки. Надявам се този отговор да помогне на някого и да спести безценно време.

person Mike Mint    schedule 29.06.2019
comment
Не мисля, че това, което се опитвате да направите, ще проработи, защото указателите на файла вече ще бъдат затворени, преди да бъдат използвани от requests.post. Следователно ни остава опцията да имаме отворени указатели. Мисля, че можем да поставим указателите в променливи и след като бъдат използвани, да ги затворим ИЛИ да имаме паралелни отваряния, да публикуваме вътре в блока with. Указателите автоматично ще бъдат затворени. - person Mooncrater; 06.07.2020

Ако имате няколко файла в списък на 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
)
person joshhu    schedule 05.09.2019

В моя случай качването на всички изображения, които са в папката, просто добавяне на ключ с индекс

напр. key = 'images' напр. 'images[0]' в цикъла

 photosDir = 'allImages'
 def getFilesList(self):
        listOfDir = os.listdir(os.path.join(os.getcwd()+photosDir))
        setOfImg = []
        for key,row in enumerate(listOfDir):
            print(os.getcwd()+photosDir+str(row) , 'Image Path')
            setOfImg.append((
                'images['+str(key)+']',(row,open(os.path.join(os.getcwd()+photosDir+'/'+str(row)),'rb'),'image/jpg')
            ))
        print(setOfImg)
        return  setOfImg
person Shamim    schedule 15.12.2020

В случай, че имате файловете от формуляр и искате да го препратите към друг URL или към API. Ето пример с множество файлове и други данни от формуляри за препращане към друг URL адрес.

images = request.files.getlist('images')
files = []
for image in images:
    files.append(("images", (image.filename, image.read(), image.content_type)))
r = requests.post(url="http://example.com/post", data={"formdata1": "strvalue", "formdata2": "strvalue2"}, files=files)
person Gopal Singh Sirvi    schedule 06.05.2021