4

不幸的是,我之前的问题因为是一个问题的“精确副本”而被关闭,而它绝对不是,特此再次强调。

它不是Python 的副本:HTTP Post a large file with streaming

那个处理流式传输大文件;我想将文件的任意块一个接一个地发送到同一个 http 连接。所以我有一个 20 MB 的文件,我想做的是打开一个 HTTP 连接,然后发送 1 MB,再发送 1 MB,等等,直到完成。使用相同的连接,因此服务器会看到一个 20 MB 的块出现在该连接上。

映射文件是我也打算做的,但是当从标准输入读取数据时,这不起作用。主要是对于第二种情况,我正在寻找这种逐部分提供的数据。

老实说,我想知道它是否可以完成 - 如果没有,我想知道,然后可以关闭这个问题。但如果可以做到,那怎么做到呢?

4

1 回答 1

6

从客户的角度来看,这很容易。您可以使用httplib的低级接口—<a href="http://docs.python.org/library/httplib.html#httplib.HTTPConnection.putrequest" rel="nofollow"> putrequestputheaderendheaderssend— 发送无论您想以任何大小的块向服务器发送任何内容。

但是您还需要指出文件的结束位置。

如果您事先知道文件的总大小,您可以简单地包含Content-Length标头,并且服务器将在那么多字节后停止读取您的请求正文。代码可能看起来像这样。

import httplib
import os.path

total_size = os.path.getsize('/path/to/file')
infile = open('/path/to/file')
conn = httplib.HTTPConnection('example.org')
conn.connect()
conn.putrequest('POST', '/upload/')
conn.putheader('Content-Type', 'application/octet-stream')
conn.putheader('Content-Length', str(total_size))
conn.endheaders()
while True:
    chunk = infile.read(1024)
    if not chunk:
        break
    conn.send(chunk)
resp = conn.getresponse()

如果事先不知道总大小,理论上的答案是分块传输编码。问题是,虽然它被广泛用于响应,但对于请求来说似乎不太受欢迎(尽管定义一样)。普通的 HTTP 服务器可能无法开箱即用地处理它。但是,如果服务器也在您的控制之下,您可以尝试手动解析请求正文中的块并将它们重新组装到原始文件中。

Content-Length另一种选择是通过同一连接将每个块作为单独的请求(带有)发送。但是您仍然需要在服务器上实现自定义逻辑。此外,您需要在请求之间保持状态。

Added 2012-12-27. There’s an nginx module that converts chunked requests into regular ones. May be helpful so long as you don’t need true streaming (start handling the request before the client is done sending it).

于 2012-10-13T11:06:10.983 回答