2011-08-11 77 views
3

我正在通過運行在Apache Tomcat/6.0.18上的Spring MVC控制器流式傳輸大文檔,因爲它很大,並且(最終)會動態生成,所以我決定使用分塊傳輸編碼。爲什麼分塊傳輸編碼不被Firefox所尊重?

import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import javax.inject.Inject; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.commons.httpclient.ChunkedOutputStream; 
import org.apache.commons.net.io.CopyStreamException; 
import org.apache.commons.net.io.Util; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 

@Controller 
public class QueryController { 

    @Inject 
    QueryService queryService; 

    @RequestMapping(value = "/stream") 
    public void hellostreamer(HttpServletResponse response) throws CopyStreamException, IOException { 

     response.setHeader("Transfer-Encoding", "chunked");  
     response.setHeader("Content-type", "text/xml"); 
     InputStream filestream = new FileInputStream("/lotsrecs.xml");  
     ChunkedOutputStream chunkStream = new ChunkedOutputStream(response.getOutputStream());  
     Util.copyStream(filestream,chunkStream); 
     chunkStream.close(); 
     chunkStream.finish(); 
    } 
} 

然而,當我在Firefox中打開這個我得到這個:

XML Parsing Error: syntax error 
Location: http://localhost:8082/streaming-mockup-1.0-SNAPSHOT/stream 
Line Number 1, Column 1: 

800 
^ 

而不是讀的塊大小爲有關的元數據流,它的閱讀他們作爲流的一部分!

使用實時的HTTP標頭,我可以看到,正在接收Transfer-Encoding頭:

HTTP/1.1 200 OK 

Server: Apache-Coyote/1.1 

Transfer-Encoding: chunked 
Content-Type: text/xml 

Date: Thu, 11 Aug 2011 18:08:07 GMT 

所以我在爲什麼塊大小沒有被正確解釋的損失。如果我使用wget發出請求,我還會在返回的文檔中看到塊大小的字符,因此不知何故它們沒有被正確編碼。任何人有一個想法爲什麼?使用wireshark查看傳輸:(請注意,整個流中「800」會重複出現)請注意0x800 = 2048,這是類ChunkedOutputStream所使用的缺省chunksize。的情況下直接創建ChunkedOutputStream

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0  
User-Agent: Wget/1.12 (linux-gnu)  
Accept: */*  
Host: localhost:8082  
Connection: Keep-Alive 

HTTP/1.1 200 OK  
Server: Apache-Coyote/1.1  
Transfer-Encoding: chunked  
Content-Type: text/xml  
Date: Thu, 11 Aug 2011 18:47:24 GMT  
Connection: close 

800 

<records> 
    <REC> 
    <FUID>412286284WOS1</FUID> 
    <UID>WOS:000292284100013</UID> 
    <static_data> 
     <summary> 
     <EWUID uid="WOS:000292284100013" year="2011"> 

如果我只是複製到輸出流中,我沒有看到的塊大小都:

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0 
User-Agent: Wget/1.12 (linux-gnu) 
Accept: */* 
Host: localhost:8082  
Connection: Keep-Alive 

HTTP/1.1 200 OK  
Server: Apache-Coyote/1.1  
Transfer-Encoding: chunked  
Content-Type: text/xml  
Date: Thu, 11 Aug 2011 18:51:05 GMT  
Connection: close  

<records> 
    <REC> 
    <FUID>412286284WOS1</FUID> 
    <UID>WOS:000292284100013</UID> 
    <static_data> 
     <summary> 

那我怎麼知道這是分塊?如果是這樣,我會不會看到塊大小?

+0

'連接:關閉'表示有些東西不能正常工作。 –

回答

11

您確定需要爲自己構建一個ChunkedOutputStream嗎?

我的理解(未被練習所理解)是ServletResponse.getOutputStream()應該在適當的情況下爲你處理分塊(比如,如果客戶端不是HTTP 1.0等等)。如果是這樣,實際獲得的回覆將被編碼爲,編碼爲,並且瀏覽器當然只知道其中的一個層。

您是否嘗試過在網絡某處運行服務器並使用Wireshark檢查事務?

更新:

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0 

HTTP /不需要1.0客戶端了解分塊編碼在所有(自然不夠的,因爲該編碼只發明瞭1.1)。

+0

更新了我的問題以顯示wireshark的輸出。 – nont

+0

很有意思!我會看到當我強制wget或curl使用HTTP 1.1時會發生什麼。謝謝! – nont

+0

太棒了:當我使用curl並直接複製流時,它會報告HTTP 1.1,如預期的那樣,我在wireshark流中看到塊大小,但看不到瀏覽器。所以你是絕對正確的:不需要自己使用ChunkedOutputStream,實際上這樣做會導致我的流錯誤地被「雙分塊」。 – nont