Python 请求-如何流式上载-部分文件

Python 请求-如何流式上载-部分文件,python,python-requests,Python,Python Requests,我的目标是使用请求对文件的一部分进行PUT,并将文件流化(即,不将其加载到内存中,然后进行PUT) 说明如何对整个文件执行此操作: 请求支持流式上载,这允许您发送大型 不将其读入内存的流或文件。流 上传,只需为您的身体提供一个类似文件的对象: 但是在我的例子中,我只想发送文件的一个块。有没有办法做到这一点 在概念上,类似于: with open('massive-body', 'rb') as f: requests.post('http://some.url/streamed', da

我的目标是使用请求对文件的一部分进行PUT,并将文件流化(即,不将其加载到内存中,然后进行PUT)

说明如何对整个文件执行此操作:

请求支持流式上载,这允许您发送大型 不将其读入内存的流或文件。流 上传,只需为您的身体提供一个类似文件的对象:

但是在我的例子中,我只想发送文件的一个块。有没有办法做到这一点

在概念上,类似于:

with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f.read(chunksize))

我只是把另外两个答案放在一起,所以如果它不在开箱即用,请耐心等待-我没有办法测试这个:


根据格雷格对我问题的回答,我认为以下几点最有效:

首先,您需要一些东西来包装打开的文件,以便限制可以读取的数据量:

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

标题显然是可选的,但当将数据流传输到服务器时,最好是一个体贴的用户,告诉服务器您要发送的内容类型。

hmm,您可能会编写一个生成器,假装是一个类似文件的对象,在幕后读取数据块,这可能很棘手,因为我不确定调用请求在文件上做了什么,但如果没有更好的结果,这似乎是可能的solution@user3012759:我尝试在类似文件的对象中搜索请求所需的内容,但没有结果。但是,请注意,它接受一个简单的生成器,因为我想您可以尝试使用一个类似于基本文件的类,该类具有
read
close
方法,如果不起作用,则继续向类中添加方法,直到请求停止抱怨为止。:)@PM2Ring chunk encoded应该也能工作,imho,设置了正确的头,创建一个生成器以chunk形式发送文件的一部分应该很容易。我不清楚你所说的“我的目标是使用请求对文件的一部分进行PUT并流式处理”是什么意思。您是否也不想将该块读入内存?如果这是你想要的,我可以帮你想出一个解决办法。请注意,如果可以将块读入内存,那么第二个代码段就可以正常工作。请注意,Greg不想上载整个文件。也许您应该将
chunk\u size
更改为其他内容,例如
blocksize
,因为Greg使用
chunksize
表示要传输的数据的总大小。FWIW,当发送
chunksize
字节时,可以轻松修改代码以打破循环,唯一的技巧是,如果
chunksize%blocksize
不是零,则最后一个块可能很短。我更新了示例,以便您可以指定最大chunksOk数。这很有效。调用者必须确保
blocksize
chunksize
的除数,但希望这不是主要问题。这看起来很有希望!因此,如果我还想在大文件中以某个偏移量开始,我可以在while语句之前在其中抛出一个seek?因此,如果我同意最后一个块很短,我就不必担心blocksize是否是chunksize的除数?谢谢,这正是我需要的!当
amount
为-1时,
data=self.file\u obj.read(剩余金额如果amount<0 else min(amount,剩余金额))
我们如何使用此方法将文件名发送到服务器?
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'})