【问题标题】:Streaming data of unknown size from client to server over HTTP in Python在 Python 中通过 HTTP 将未知大小的数据从客户端流式传输到服务器
【发布时间】:2012-10-03 23:52:34
【问题描述】:

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

它不是 Python: HTTP Post a large file with streaming 的重复项

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

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

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

【问题讨论】:

  • 您寻求的唯一不同行为是加扰文件吗?
  • 我想将文件的任意块一个接一个地发送到同一个 http 连接。 这称为流式传输。 (...) 但从标准输入读取数据时不起作用。在这种情况下,您的问题具有误导性,因为它明确提到了 file,这意味着输入数据的大小是已知的。

标签: python http upload


【解决方案1】:

从客户的角度来看,这很容易。您可以使用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()

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

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

于 2012 年 12 月 27 日添加。 an nginx module 将分块请求转换为常规请求。只要您不需要真正的流式传输,可能会有所帮助(在客户端完成发送之前开始处理请求)。

【讨论】:

  • 非常好,看起来就像我需要的一样。会努力的,大概可以接受这个答案。总大小通常是未知的 - 以防我们通过标准输入管道输入文件(这是 mmap 不起作用的地方),但我认为能够以某种方式解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 2014-01-19
  • 2012-02-11
相关资源
最近更新 更多