問題描述
不幸的是,我之前的問題因?yàn)槭且粋€問題的精確副本"而被關(guān)閉,而它絕對不是,特此再次說明.
As unfortunately my previous question got closed for being an "exact copy" of a question while it definitely IS NOT, hereby again.
它不是 Python: HTTP Post a large file帶流媒體
那個處理流式傳輸一個大文件;我想將文件的任意塊一個接一個地發(fā)送到同一個 http 連接.所以我有一個 20 MB 的文件,我想做的是打開一個 HTTP 連接,然后發(fā)送 1 MB,再發(fā)送 1 MB,等等,直到完成.使用相同的連接,因此服務(wù)器會看到一個 20 MB 的塊出現(xiàn)在該連接上.
That one deals with streaming a big file; I want to send arbitrary chunks of a file one by one to the same http connection. So I have a file of say 20 MB, and what I want to do is open an HTTP connection, then send 1 MB, send another 1 MB, etc, until it's complete. Using the same connection, so the server sees a 20 MB chunk appear over that connection.
映射文件是我也打算做的,但是當(dāng)從標(biāo)準(zhǔn)輸入讀取數(shù)據(jù)時這不起作用.主要針對第二種情況,我正在尋找這種逐部分提供的數(shù)據(jù).
Mmapping a file is what I ALSO intend to do, but that does not work when the data is read from stdin. And primarily for that second case I an looking for this part-by-part feeding of data.
老實(shí)說,我想知道它是否可以完成 - 如果不能,我想知道,然后可以關(guān)閉問題.但如果能做到,那怎么做到呢?
Honestly I wonder whether it can be done at all - if not, I'd like to know, then can close the issue. But if it can be done, how could it be done?
推薦答案
從客戶的角度來看,這很容易.你可以使用httplib
的底層接口——putrequest
, putheader
, endheaders
和 send
— 以任意大小的塊向服務(wù)器發(fā)送您想要的任何內(nèi)容.
From the client’s perspective, it’s easy. You can use httplib
’s low-level interface—putrequest
, putheader
, endheaders
, and send
—to send whatever you want to the server in chunks of any size.
但您還需要指明文件的結(jié)束位置.
But you also need to indicate where your file ends.
如果您事先知道文件的總大小,您可以簡單地包含 Content-Length
標(biāo)頭,服務(wù)器將在這么多字節(jié)后停止讀取您的請求正文.代碼可能如下所示.
If you know the total size of the file in advance, you can simply include the Content-Length
header, and the server will stop reading your request body after that many bytes. The code may then look like this.
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()
如果事先不知道總大小,理論上的答案是分塊傳輸編碼一個>.問題是,雖然它被廣泛用于響應(yīng),但對于請求來說似乎不太受歡迎(盡管定義一樣).普通的 HTTP 服務(wù)器可能無法開箱即用地處理它.但是,如果服務(wù)器也在您的控制之下,您可以嘗試手動解析請求正文中的塊并將它們重新組裝到原始文件中.
If you don’t know the total size in advance, the theoretical answer is the chunked transfer encoding. Problem is, while it is widely used for responses, it seems less popular (although just as well defined) for requests. Stock HTTP servers may not be able to handle it out of the box. But if the server is under your control too, you could try manually parsing the chunks from the request body and reassembling them into the original file.
另一種選擇是通過同一連接將每個塊作為單獨(dú)的請求(使用 Content-Length
)發(fā)送.但是您仍然需要在服務(wù)器上實(shí)現(xiàn)自定義邏輯.此外,您需要在請求之間保持狀態(tài).
Another option is to send each chunk as a separate request (with Content-Length
) over the same connection. But you still need to implement custom logic on the server. Moreover, you need to persist state between requests.
添加于 2012-12-27. 有 一個 nginx 模塊 可以轉(zhuǎn)換將請求分塊為常規(guī)請求.只要您不需要真正的流式傳輸(在客戶端完成發(fā)送之前開始處理請求),這可能會有所幫助.
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).
這篇關(guān)于在 Python 中通過 HTTP 將未知大小的數(shù)據(jù)從客戶端流式傳輸?shù)椒?wù)器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!