【问题标题】:Uncompress GZIPed HTTP Response in Java在 Java 中解压缩 GZIPed HTTP 响应
【发布时间】:2014-01-09 19:05:15
【问题描述】:

我正在尝试使用 GZIPInputStream 解压缩 GZIPed HTTP 响应。但是,当我尝试读取流时,我总是遇到同样的异常:java.util.zip.ZipException: invalid bit length repeat

我的 HTTP 请求标头:

GET www.myurl.com HTTP/1.0\r\n
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2) Gecko/20100115 Firefox/3.6\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3\r\n
Accept-Encoding: gzip,deflate\r\n
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\r\n
Keep-Alive: 115\r\n
Connection: keep-alive\r\n
X-Requested-With: XMLHttpRequest\r\n
Cookie: Some Cookies\r\n\r\n

在 HTTP 响应标头的末尾,我得到 path=/Content-Encoding: gzip,然后是压缩后的响应。

我尝试了 2 个类似的代码来解压缩:

更新:在以下代码中,tBytes = (the string after 'path=/Content-Encoding: gzip').getBytes ();

GZIPInputStream  gzip = new GZIPInputStream (new ByteArrayInputStream (tBytes));

StringBuffer  szBuffer = new StringBuffer ();

byte  tByte [] = new byte [1024];

while (true)
{
    int  iLength = gzip.read (tByte, 0, 1024); // <-- Error comes here

    if (iLength < 0)
        break;

    szBuffer.append (new String (tByte, 0, iLength));
}

还有我在这个论坛上看到的这个:

InputStream     gzipStream = new GZIPInputStream   (new ByteArrayInputStream (tBytes));
Reader          decoder    = new InputStreamReader (gzipStream, "UTF-8");//<- I tried ISO-8859-1 and get the same exception
BufferedReader  buffered   = new BufferedReader    (decoder);

我猜这是编码错误。

最好的问候,

账单

【问题讨论】:

    标签: java gzip httpresponse compression


    【解决方案1】:

    您没有在此处展示如何获得用于设置 gzip 流的 tBytes

    GZIPInputStream  gzip = new GZIPInputStream (new ByteArrayInputStream (tBytes));
    

    一种解释是您将整个 HTTP 响应包含在 tBytes 中。相反,它应该只是 HTTP 标头之后的内容。

    另一种解释是回复是chunked

    edit:您将内容编码行之后的数据作为消息正文。但是,根据 HTTP 1.1 规范,标头字段没有任何特定的顺序,所以这是非常危险的。

    正如HTTP specification 的这一部分所解释的,请求或响应的消息正文不是出现在特定标头字段之后,而是在第一个空行之后

    请求(第 5 节)和响应 (第 6 节)消息使用泛型 RFC 822 [9] 的消息格式 传输实体(有效载荷 消息)。两种类型的消息 由一条起始线组成,零个或多个 标头字段(也称为 “标题”),一个空行(即, 在 CRLF 之前没有任何内容的行) 表示标题的结尾 字段,可能还有消息正文。

    您仍然没有展示您是如何准确地撰写tBytes,但在这一点上,我认为您错误地在尝试解压缩的数据中包含了空行。消息正文在空行的 CRLF 字符之后开始。

    我可以建议您改用httpclient 库来提取邮件正文吗?

    【讨论】:

    • 嗨,维姆。感谢您的回答。我已更新消息以解释我如何获得 tBytes。我不认为响应是分块的,因为有一个 Content-Length 标头。但我不确定。 bill0ute
    • 嗨,维姆。我正在尝试使用 HttpClient 包,但找不到 Java Doc。我只得到例子。你能给我一个连接到套接字并发送获取请求的小例子吗?谢谢
    • 看看教程,它是一个简单的例子,用于获取 HTTP GET 的响应主体:hc.apache.org/httpclient-3.x/tutorial.html 在你的情况下,你需要像现在处理 @987654330 一样处理 responseBody @.
    • 嗨。 HTTPClient 有效!它很棒!你在写,响应是分块的。但我无法取消对结果进行分块,因为我有一个例外:“Bad Chunk Header”。我应该打开一个新线程吗?或者解决方案很简单?谢谢!
    • @bill0ute:我会提出一个新问题。
    【解决方案2】:

    嗯,我可以在这里看到问题;

    int  iLength = gzip.read (tByte, 0, 1024);
    

    使用以下方法解决此问题;

            byte[] buff = new byte[1024];
    byte[] emptyBuff = new byte[1024];
                                StringBuffer unGzipRes = new StringBuffer();
    
                                int byteCount = 0;
                                while ((byteCount = gzip.read(buff, 0, 1024)) > 0) {
                                    // only append the buff elements that
                                    // contains data
                                    unGzipRes.append(new String(Arrays.copyOf(
                                            buff, byteCount), "utf-8"));
    
                                    // empty the buff for re-usability and
                                    // prevent dirty data attached at the
                                    // end of the buff
                                    System.arraycopy(emptyBuff, 0, buff, 0,
                                            1024);
                                }
    

    【讨论】:

      猜你喜欢
      • 2022-06-29
      • 2012-02-12
      • 2010-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      相关资源
      最近更新 更多