多次请求将文件上载到URL第二次失败



我试图将相同的文件上传到两个不同的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请求没有文件信息。我是做错了什么,还是一个bug?


奇怪的是,这是有效的:

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'}

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

我知道这个问题很老了,但我遇到了同样的问题并解决了它。以下是对问题的解释和解决方案。

您的示例中发生了什么

在你的代码示例中,当你写:

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只读取作为参数给定的文件对象。它不会重置字节流。如果您使用同一个文件对象两次,则需要自己重置它。

最新更新