2010-03-07 86 views
20

我目前正試圖在轉碼過程之後將內容流式傳輸到網絡。這通常可以通過將二進制文件寫入我的Web流而正常工作,但是某些瀏覽器(特別是IE7,IE8)不喜歡沒有在HTTP標頭中定義的Content-Length。我相信「有效」標題應該有這個集合。用於未知內容的HTTP頭長度

當您有一個未知的內容長度時,將內容傳輸到網絡的正確方法是什麼?轉碼過程可能需要一段時間,所以我想在它完成時開始流式傳輸。

回答

18

嘗試將它們連同Transfer-Encoding:chunked一起發送。 wikipedia中的更多詳細信息。

更新按照該意見,在這裏有一個例子是 「ChunkedOutputStream」 在Java中怎麼可能看起來像:

package com.stackoverflow.q2395192; 

import java.io.IOException; 
import java.io.OutputStream; 

public class ChunkedOutputStream extends OutputStream { 

    private static final byte[] CRLF = "\r\n".getBytes(); 
    private OutputStream output = null; 

    public ChunkedOutputStream(OutputStream output) { 
     this.output = output; 
    } 

    @Override 
    public void write(int i) throws IOException { 
     write(new byte[] { (byte) i }, 0, 1); 
    } 

    @Override 
    public void write(byte[] b, int offset, int length) throws IOException { 
     writeHeader(length); 
     output.write(CRLF, 0, CRLF.length); 
     output.write(b, offset, length); 
     output.write(CRLF, 0, CRLF.length); 
    } 

    @Override 
    public void flush() throws IOException { 
     output.flush(); 
    } 

    @Override 
    public void close() throws IOException { 
     writeHeader(0); 
     output.write(CRLF, 0, CRLF.length); 
     output.write(CRLF, 0, CRLF.length); 
     output.close(); 
    } 

    private void writeHeader(int length) throws IOException { 
     byte[] header = Integer.toHexString(length).getBytes(); 
     output.write(header, 0, header.length); 
    } 

} 

...這基本上可以用作:

OutputStream output = new ChunkedOutputStream(response.getOutputStream()); 
output.write(....); 

在源代碼中可以看到,每個數據塊都有一個表示十六進制數據長度,CRLF,實際數據和CRLF的標題。流的結尾由表示0長度的頭部和兩個CRLF表示。

注:儘管例子,你其實不需要它在一個JSP/Servlet的web應用。只要內容長度未在響應中設置,webcontainer就會自動將它們以塊的形式傳輸。

+0

我嘗試使用塊,並且Firefox在接收它們時會鎖定。我正在傳輸二進制數據,我是否必須將其轉換爲十六進制才能使用塊?有沒有.NET庫可用於此? – jocull 2010-03-07 17:52:41

+1

不,你不需要轉換。如果不預先指定內容長度,我會希望.NET自動處理它。 – 2010-03-07 19:04:39

+0

點擊'chunked'和維基百科鏈接後面的鏈接,瞭解它應該是什麼樣子。我不會做.NET,所以我不能付出太多的代價,但是我可以給出一個基於Java的示例,以擴展'OutputStream'的風格。讓我們知道你是否想看到它。 – BalusC 2010-03-08 00:37:36

2

就跟BalusC的優秀帖子一樣,這裏是我在C#中使用的代碼。在從進程上的STDOUT接收到數據後,我將數據手動直接分塊爲HTTP輸出流。

int buffSize = 16384; 
byte[] buffer = new byte[buffSize]; 
byte[] hexBuff; 
byte[] CRLF = Encoding.UTF8.GetBytes("\r\n"); 

br = new BinaryReader(transcoder.StandardOutput.BaseStream); 

//Begin chunking... 
int ret = 0; 
while (!transcoder.HasExited && (ret = br.Read(buffer, 0, buffSize)) > 0) 
{ 
    //Write hex length... 
    hexBuff = Encoding.UTF8.GetBytes(ret.ToString("X")); 
    e.Context.Stream.Write(hexBuff, 0, hexBuff.Length); 

    //Write CRLF... 
    e.Context.Stream.Write(CRLF, 0, CRLF.Length); 

    //Write byte content... 
    e.Context.Stream.Write(buffer, 0, ret); 

    //Write CRLF... 
    e.Context.Stream.Write(CRLF, 0, CRLF.Length); 
} 
//End chunking... 
//Write hex length... 
hexBuff = Encoding.UTF8.GetBytes(0.ToString("X")); 
e.Context.Stream.Write(hexBuff, 0, hexBuff.Length); 
+0

好的工作,很高興它幫助你。 – BalusC 2010-03-08 18:20:33