我的目标是使用请求对文件的一部分进行PUT并流式传输文件(即,不将其加载到内存中然后执行PUT)。
This page解释了如何为整个文件执行此操作:
请求支持流式上传,允许您发送大型内容 流或文件而不将它们读入内存。流和 上传,只需为您的身体提供类似文件的对象:
with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f)
但是在我的情况下,我只想发送一个文件块。有没有办法实现这个目标?
在概念上,例如:
with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f.read(chunksize))
答案 0 :(得分:6)
根据格雷格对我的问题的回答,我认为以下内容最有效:
首先,您需要一些东西来打开您的打开文件,以便限制可以读取的数据量:
class FileLimiter(object):
def __init__(self, file_obj, read_limit):
self.read_limit = read_limit
self.amount_seen = 0
self.file_obj = file_obj
# So that requests doesn't try to chunk the upload but will instead stream it:
self.len = read_limit
def read(self, amount=-1):
if self.amount_seen >= self.read_limit:
return b''
remaining_amount = self.read_limit - self.amount_seen
data = self.file_obj.read(min(amount, remaining_amount))
self.amount_seen += len(data)
return data
这应该大致可以作为一个好的包装器对象。那你就像这样使用它:
with open('my_large_file', 'rb') as file_obj:
file_obj.seek(my_offset)
upload = FileLimiter(file_obj, my_chunk_limit)
r = requests.post(url, data=upload, headers={'Content-Type': 'application/octet-stream'})
标题显然是可选的,但在将数据流式传输到服务器时,最好成为一个体贴的用户并告诉服务器您要发送的内容类型。
答案 1 :(得分:3)
我只是把另外两个答案放在一起,所以请耐心等待,如果它没有开箱即用 - 我无法测试这个:
Lazy Method for Reading Big File in Python?
http://docs.python-requests.org/en/latest/user/advanced/#chunk-encoded-requests
def read_in_chunks(file_object, blocksize=1024, chunks=-1):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while chunks:
data = file_object.read(blocksize)
if not data:
break
yield data
chunks -= 1
requests.post('http://some.url/chunked', data=read_in_chunks(f))