【问题标题】:why is chunked transfer encoding not being respected by Firefox?为什么 Firefox 不遵守分块传输编码?
【发布时间】:2011-08-11 18:20:05
【问题描述】:

我正在通过在 Apache Tomcat/6.0.18 上运行的 Spring MVC 控制器流式传输大型文档

因为它很大,并且(最终)会动态生成,我决定使用分块传输编码。

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
^

不是将块大小作为有关流的元数据来读取,而是将它们作为流的一部分来读取!

使用 Live 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类使用的默认块大小。

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">

如果我只是直接复制到输出流而不创建 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:51:05 GMT    
Connection: close    

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

那么我怎么知道这是否是分块的呢?如果是,我不会看到块大小吗?

【问题讨论】:

  • “连接:关闭”表示有些东西不能正常工作。

标签: spring streaming transfer-encoding


【解决方案1】:

您确定需要为自己构建一个ChunkedOutputStream 吗?

我的理解(不受实践影响)是ServletResponse.getOutputStream() 应该在适当的情况下为您处理分块(例如,如果客户端不是 HTTP 1.0,等等)。如果这是真的,那么实际发送的回复将是分块编码inside分块编码,而浏览器当然只知道其中一层。

您是否尝试过通过网络在某处运行服务器并使用 Wireshark 检查交易?

更新:

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

HTTP/1.0 客户端根本不需要理解分块编码(很自然,因为这种编码只是为 1.1 发明的)。

【讨论】:

  • 非常有趣!我会看看当我强制 wget 或 curl 使用 HTTP 1.1 时会发生什么。谢谢!
  • 真棒:当我使用 curl 并直接复制流时,它会报告 HTTP 1.1,并且正如预期的那样,我看到了 wireshark 流中的块大小,但没有在浏览器中看到。所以你是绝对正确的:我自己不需要使用 ChunkedOutputStream - 实际上这样做会导致我的流被错误地“双分块”。
猜你喜欢
  • 2018-05-16
  • 2010-09-25
  • 2017-12-06
  • 2022-08-13
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多