35

Python requests 模块提供了关于如何在单个请求中上传单个文件的良好文档:

 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

是否可以使用此模块在单个请求中上传文件列表,以及如何上传?

4

8 回答 8

46

要在单个请求中上传具有相同键值的文件列表,您可以创建一个元组列表,其中每个元组中的第一项作为键值,文件对象作为第二个:

files = [('file', open('report.xls', 'rb')), ('file', open('report2.xls', 'rb'))]
于 2013-12-25T06:51:50.660 回答
24

通过添加多个字典条目可以上传具有不同键值的多个文件:

files = {'file1': open('report.xls', 'rb'), 'file2': open('otherthing.txt', 'rb')}
r = requests.post('http://httpbin.org/post', files=files)
于 2013-08-12T10:37:35.233 回答
21

文档包含一个明确的答案。

引:

您可以在一个请求中发送多个文件。例如,假设您要将图像文件上传到具有多个文件字段“图像”的 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',
#  ...
# }
于 2014-10-29T20:15:17.780 回答
2

您需要创建一个文件列表来上传多个图像:

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/

于 2019-04-23T16:00:46.053 回答
1

如果您有表单中的文件并希望将其转发到其他 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)
于 2021-05-06T14:34:17.650 回答
1

我有点困惑,但是直接在请求中打开文件(但是官方请求指南中也写了同样的内容)并不是那么“安全”。

试试看嘛:

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

现在我们没有收到错误,所以我建议使用这种方式上传多个文件,否则您可能会收到一些错误。希望这个答案能很好地帮助别人并节省宝贵的时间。

于 2019-06-29T01:41:09.283 回答
0

In my case uploading all the images which are inside the folder just adding key with index

e.g. key = 'images' to e.g. 'images[0]' in the loop

 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
于 2020-12-15T13:59:54.047 回答
0

如果您在 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
)
于 2019-09-05T13:12:38.653 回答