请求 - 如何流上传 - 部分文件

时间:2015-04-21 14:33:21

标签: python python-requests

我的目标是使用请求对文件的一部分进行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))

2 个答案:

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