【问题标题】:Requests file upload multiple times to a URL fails the second time多次请求文件上传到一个 URL 失败第二次
【发布时间】:2022-04-07 17:13:24
【问题描述】:

我试图将相同的文件上传到两个不同的 URL,但奇怪的是这不起作用。第二个POST 请求从未得到文件。所以,我尝试实现一个最小的例子来展示发生了什么:

import requests
files = [('file',open(os.path.join(os.getcwd(),"textFile.txt")))]
op1 = requests.post("https://httpbin.org/post",files=files)
op2 = requests.post("https://httpbin.org/post",files=files)
print(op1.json())
print("================")
print(op2.json())

所以,我希望这两个结果都包含 file 文件和文本信息。但我得到的是:

{'args': {}, 'data': '', 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '186', 'Content-Type': 'multipart/form-data; boundary=196646c7550f74ac2d0a130f90350f1b', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c87c3-3355ec90b9973128fe25d6d0'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}
================
{'args': {}, 'data': '', 'files': {'file': ''}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '148', 'Content-Type': 'multipart/form-data; boundary=b9e13ed8891641a6b10faaf5cded597b', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c87c4-38a66f895aee787c28ce8910'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}

所以,如您所见,第二个POST 请求没有文件信息。我在这里做错了什么还是一个错误?


奇怪的是,这行得通:

import requests
files = [('file',open(os.path.join(os.getcwd(),"textFile.txt")))]
op1 = requests.post("https://httpbin.org/post",files=files)
files = [('file',open(os.path.join(os.getcwd(),"textFile.txt")))]
op2 = requests.post("https://httpbin.org/post",files=files)

print(op1.json())
print("================")
print(op2.json())

输出:

{'args': {}, 'data': '', 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '186', 'Content-Type': 'multipart/form-data; boundary=870c451b9854b5d7265b0f0681f9b4bb', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c8ad9-c0469aaa6d8a4d0023885a4d'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}
================
{'args': {}, 'data': '', 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '186', 'Content-Type': 'multipart/form-data; boundary=aadfc00c1cb0a6f1019eb2080f2a8461', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c8ada-1776e20418dda96c39a1bc48'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}

因此,requests 使用该文件可能会被关闭,但:

import requests
files = [('file',open(os.path.join(os.getcwd(),"textFile.txt")))]
op1 = requests.post("https://httpbin.org/post",files=files)
#files = [('file',open(os.path.join(os.getcwd(),"textFile.txt")))]
print(files[0][1].closed) #<=============
op2 = requests.post("https://httpbin.org/post",files=files)

print(op1.json())
print("================")
print(op2.json())

给予:

False
{'args': {}, 'data': '', 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '186', 'Content-Type': 'multipart/form-data; boundary=a93b1c26216d7d905a5b684b0c32fe51', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c8b69-23e6606819acb268e57edf78'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}
================
{'args': {}, 'data': '', 'files': {'file': ''}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '148', 'Content-Type': 'multipart/form-data; boundary=222f5304294b85527ae355bbd714a4e3', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.22.0', 'X-Amzn-Trace-Id': 'Root=1-5f0c8b6c-5ded97a4da068830f0b38840'}, 'json': None, 'origin': 'XX.XX.XX.XX', 'url': 'https://httpbin.org/post'}

所以我绝对不知道这里发生了什么。

【问题讨论】:

    标签: python post file-upload python-requests


    【解决方案1】:

    我知道这个问题已经很老了,但我遇到了同样的问题并修复了它。这是问题的解释和解决方案。

    在您的示例中发生了什么

    在您的代码示例中,当您编写时:

    import requests
    files = [('file', open("textFile.txt"))]
    op1 = requests.post("https://httpbin.org/post", files=files)
    op2 = requests.post("https://httpbin.org/post", files=files)
    

    您实际上是在创建某种io.IOBase(在这种情况下特别是io.TextIOWrapper)。 第一个post 请求将读取该文件,将文件的流位置移动到末尾。第二个post 请求使用完全相同的实例(您不会再次打开文件)。文件流现在指向文件末尾,没有可读取的内容。然后你发送一个空文件。

    您的示例确实可以简化为“我两次调用fileobj.read(),第二次调用显示内容为空”。

    fobj = open("textFile.txt")
    print(fobj.read())  # "I'm Mr. TextSeeks look at meeee!"
    print(fobj.read())  # ""
    

    这就是您的版本再次打开文件没有遇到任何问题的原因。

    可能的解决方案

    一种可能的解决方案是使用seek 方法重置字节流的位置:

    fobj = open("textFile.txt")
    print(fobj.read())  # "I'm Mr. TextSeeks look at meeee!"
    fobj.seek(0)
    print(fobj.read())  # "I'm Mr. TextSeeks look at meeee!"
    

    应用于初始代码示例:

    import requests
    files = [('file',open("textFile.txt"))]
    op1 = requests.post("https://httpbin.org/post", files=files)
    files[0][1].seek(0)
    op2 = requests.post("https://httpbin.org/post", files=files)
    
    print(op1.json())  # {..., 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, ...}
    print(op2.json())  # {..., 'files': {'file': "I'm Mr. TextSeeks look at meeee!"}, ...}
    

    作为总结:requests 只读取作为参数给出的文件对象。它不会重置字节流。如果你两次使用同一个文件对象,你需要自己重置它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 2019-05-11
      • 2023-01-25
      相关资源
      最近更新 更多