使用python请求模块在单个请求中上载多个文件

时间:2013-08-12 03:57:04

标签: python-requests multiple-file-upload

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

 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

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

8 个答案:

答案 0 :(得分:21)

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

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

答案 1 :(得分:13)

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

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

答案 2 :(得分:10)

documentation包含明确的答案。

引用:

  

您可以在一个请求中发送多个文件。例如,假设你   想要将图像文件上传到具有多个文件字段的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',
#  ...
# }

答案 3 :(得分:0)

您需要创建文件列表以上传多张图像:

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/

答案 4 :(得分:0)

我有点困惑,但是直接在请求中打开文件(无论如何在官方请求指南中写明)都不是那么“安全”。

只需尝试:

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

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

答案 5 :(得分:0)

如果python列表中有多个文件,则可以理解地使用<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/appTourViewPager" android:layout_width="0dp" android:layout_height="0dp" android:layout_above="@+id/appTourIndicator" app:layout_constraintBottom_toTopOf="@+id/appTourIndicator" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <me.relex.circleindicator.CircleIndicator3 android:id="@+id/appTourIndicator" android:layout_width="match_parent" android:layout_height="45dp" app:ci_drawable="@drawable/circle_radius_selected" app:ci_drawable_unselected="@drawable/circle_radius_unselected" app:ci_height="6dp" app:ci_margin="5dp" app:ci_width="6dp" app:layout_constraintBottom_toBottomOf="@id/appTourViewPager" app:layout_constraintBottom_toTopOf="@+id/btnSignIn" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <Button android:id="@+id/btnSignIn" style="?android:borderlessButtonStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:maxLines="3" android:textAlignment="center" android:textAppearance="?android:attr/textAppearanceMedium" app:layout_constraintBottom_toTopOf="@+id/btnGetStartedNow" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <Button android:id="@+id/btnGetStartedNow" style="@style/Button.Blue" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="16dp" android:paddingRight="16dp" android:text="@string/getStartedNow" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> 遍历requests post files参数中的文件。

eval()

答案 6 :(得分:0)

在我的情况下,上传文件夹内的所有图像只是添加带有索引的键

例如键=“图片”,例如循环中的“ 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

答案 7 :(得分:0)

如果您有表单中的文件并希望将其转发到其他 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)