在Python中通过HTTP将未知大小的数据从客户端流式传输到服务器



不幸的是,我之前的问题因为是一个问题的"精确副本"而被关闭,而它肯定不是。

它不是Python的副本:HTTP发布一个带有流的大文件

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

我还打算映射一个文件,但当从stdin读取数据时,这是不起作用的。主要针对第二种情况,我会逐个查找数据。

老实说,我想知道这是否可以做到——如果不能,我很想知道,那么可以解决这个问题。但是,如果可以做到,又如何做到呢?

从客户的角度来看,这很容易。您可以使用httplib的底层接口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)发送。但是您仍然需要在服务器上实现自定义逻辑。此外,您需要在请求之间保持状态。

添加了2012-12-27。有一个nginx模块可以将分块请求转换为常规请求。只要你不需要真正的流媒体(在客户端发送请求之前开始处理请求),这可能会很有帮助。

最新更新