2012-08-01 22 views
2

我有這個視圖稱爲虛擬,我想從我的服務器流mp3,我想流到<audio src="/stream">標記,以便客戶端可以立即開始播放文件,而無需等待整個文件。標題在金字塔發送chunked二進制

def dummy(request): 
    headers = { 
     'Content-Transfer-Encoding': 'binary', 
     'Content-Type': 'audio/mpeg', 
     'Transfer-Encoding': 'chunked', 
     'Connection': 'keep-alive', 
     'Cache-Control': 'no-cache' 
    } 
    with open('songer.mp3') as handle: 
     while True: 
      bytes = handle.read(CHUNK) 
      if not bytes: 
       break 
      return Response(bytes, headers=headers) 

但我發現了由鉻ERR_INVALID_CHUNKED_ENCODING,也是我不知道如果我返回響應會工作,因爲那豈不是結束反應一旦進入到返回的方式嗎?

回答

5

你是對的,你不能從視圖返回多個響應......或者實際上,通常在循環中從一個函數發出多個返回 - 第一個return語句將終止該函數。

看看Response.body_fileResponse.app_iter屬性。

response.app_iter: 可迭代(例如列表或發電機),將 產生響應的內容。這也可以通過 response.body(一個字符串),response.unicode_body(一個unicode對象, 通過response.charset通知)和response.body_file(一個像文件的 對象;寫入它附加到app_iter)

body_file可用於寫入主體的類文件對象。如果 您通過了列表app_iter,那麼app_iter將被 寫入修改。

http://docs.pylonsproject.org/projects/pyramid/en/latest/api/response.html

如果你這樣做

request.response.body_file = open('songer.mp3') 
# set any headers here 
return response 

該文件會從磁盤讀取,並立即發送給客戶端,而不必等待整個文件。我不確定在這裏是否需要分塊傳輸編碼。

的WebOb文檔具有更爲複雜的文件服務應用程序,它可以有效地處理範圍請求的例子:http://docs.webob.org/en/latest/file-example.html

+0

如果上面的代碼自動處理字節流,然後這就是我要找的。我會玩它,謝謝 – Marconi 2012-08-01 23:34:25

+0

謝爾蓋:謝謝你的作品,但我面臨另一個問題。如果整個mp3已經被讀取並保存在一個變量中,那麼我該如何創建迭代器並將字節拆分成塊並使用yiel返回? – Marconi 2012-08-02 06:59:39

+0

是的,這將工作。或者使用StringIO將變量轉換爲類文件對象並將其分配給Response.body_file。雖然我不確定上述方法與僅將您的變量分配給Request.body相比有什麼不同。我的意思是,在服務器上沒有什麼特別的事情要讓客戶端在播放/顯示一小部分文件時立即播放/顯示文件 - 這就是WWW從一開始就工作的原因。您只需避免在提供服務前將整個大文件讀入內存,這就是body_file和app_iter的用途。 – Sergey 2012-08-02 10:26:28