【问题标题】:Uploading multiple files in a single request using python requests module使用 python requests 模块在单个请求中上传多个文件
【发布时间】:2013-08-12 03:57:03
【问题描述】:

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

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

【问题讨论】:

  • 为什么没有被接受的答案?下面的高票回答还不够吗?
  • 平/碰撞。这些答案中的任何一个都足够了吗?

标签: python-requests multiple-file-upload


【解决方案1】:

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

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

【讨论】:

  • 假设我有一个文件名列表,有没有办法通过列表理解来做到这一点?
  • @MatthewSemik file_names = ["abc.txt", "pqr.txt" ] files = [('file', open(f, 'rb')) for f in file_names]
  • 谢谢,对我来说很好
【解决方案2】:

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

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

【讨论】:

  • 有趣。会尝试你的方法。我尝试 list 的原因是因为 Flask (python web framework) 说 files 是一个 multidict 并且访问所有文件上传的方法是:request.files.getall('file')
  • 我需要自己关闭文件描述符吗?还是会像open('file', 'r') as f..一样自动关闭?
  • @Lukasa,R 中是否有类似方法的解决方案?
【解决方案3】:

documentation 包含明确的答案。

引用:

您可以在一个请求中发送多个文件。例如,假设你 想要将图像文件上传到具有多个文件字段的 HTML 表单 “图片”:

到 这样做,只需将文件设置为 (form_field_name, 文件信息):

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',
#  ...
# }

【讨论】:

  • file_info 可以采取什么形式?我可以省略内容类型吗? file_info 还有什么可以作为的一部分?文档没有详细说明。
  • @AmauryRodriguez 我建议您查看所有这些详细信息的源代码。
【解决方案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))
    

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

    【讨论】:

    • 我认为您尝试做的事情不会奏效,因为文件指针将已经关闭,它们被requests.post 使用之前。因此,我们可以选择打开指针。我认为,我们可以将指针放在变量中,在使用它们之后,关闭它们或并行打开,将 inside 发布到 with 块中。指针会自动关闭。
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

      如果您在 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
      )
      

      【讨论】:

        【解决方案8】:

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

        例如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
        

        【讨论】:

          【解决方案9】:

          使用这些方法文件会自动关闭。

          方法一

          with open("file_1.txt", "rb") as f1, open("file_2.txt", "rb") as f2:
              files = [f1, f2]
              response = requests.post('URL', files=files)
          

          但是当您打开多个文件时,这可能会变得很长

          方法二:

          files = [open("forms.py", "rb"), open("data.db", "rb")]
          response = requests.post('URL', files=files)
          
          # Closing all Files
          for file in files: 
              file.close()
          

          【讨论】:

            猜你喜欢
            • 2013-02-02
            • 2013-03-12
            • 2013-03-30
            • 2020-11-02
            • 1970-01-01
            • 1970-01-01
            • 2018-02-09
            • 1970-01-01
            • 2012-10-20
            相关资源
            最近更新 更多