HttpURLConnection 不解压缩 Gzip
Posted
技术标签:
【中文标题】HttpURLConnection 不解压缩 Gzip【英文标题】:HttpURLConnection not decompressing Gzip 【发布时间】:2013-09-24 18:58:19 【问题描述】:我正在尝试在 Gingerbread+ android 设备上使用 HttpURLConnection,但遇到 gzip 编码问题。根据文档
“在 Gingerbread 中,我们添加了透明响应压缩。 HttpURLConnection 将自动将此标头添加到传出 请求,并处理相应的响应:
接受编码:gzip"
问题是这实际上并没有发生。根本没有添加 Accept-Encoding: gzip 标头。如果我手动添加它,我希望它的解压缩部分可以通过 connection.openInputStream() 自动返回一个 GZipInputStream 但它只返回一个普通的 InputStream。
有人经历过吗?我还没有看到任何关于这种情况的帖子,所以这很奇怪。该项目是针对 API 17 编译的,因此不应该成为问题,并且设备正在运行 4.3。
谢谢。
【问题讨论】:
The Accept-Encoding: gzip header is not getting added at all.
你是如何验证这一点的?
响应未返回 Content-Encoding: gzip。它也不在 urlConnection.getRequestProperties() 中。添加 Accept-Encoding: gzip 通过 addRequestProperty 导致响应返回 gzip 压缩,所以我决定它没有被添加。
【参考方案1】:
我遇到了同样的问题,它与 HTTPS 有关。如果你打电话:
URL url = new URL("https://www.example.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
您实际上得到了一个不会自动处理 gzip 的 HttpsURLConnection(HttpURLConnection 的子类)的实例。 在这些情况下,您可以:
conn.setRequestProperty("Accept-Encoding", "gzip");
...
InputStream inStream = new GZIPInputStream(conn.getInputStream());
【讨论】:
HttpURLConnection 默认添加 gzip 头 @Nik,显然您在发表评论之前没有阅读答案。重点是 HttpURLConnection 添加了标题,但 HttpsURLConnection (带有“s”)没有。这就是导致问题中提到的问题的原因。子类的行为不同。 似乎确实没有在 Gingerbread 中为 https 自动添加标题,但自从冰淇淋三明治以来,它为 https 正确添加。在 ICS 中,http 和 https 实现共享相同的 HTTP 引擎。 这可能是因为加密压缩数据可能会泄漏数据 - 即压缩连接可能不安全。参见众所周知的“CRIME”或“BREACH”攻击。【参考方案2】:由于 Android Gingerbread (http) 和 ICS (http + https),当您使用 Http(s)URLConnection
时,Android 会自动添加 Accept-Encoding: gzip
标头,但前提是您没有先自己添加它.
在这种情况下,如果服务器返回 gzip 编码的内容,您将自动获得 GZIPInputStream
并且 Content-Encoding: gzip
标头将从响应中删除。这就是它被称为 transparent 的原因:因此客户端无法通过查看流内容或标头来区分压缩或未压缩响应。
但是,如果您自己手动添加 Accept-Encoding: gzip
标头,则该请求的透明 gzip 处理将被禁用,并且如果服务器返回 gzip 压缩的内容,则您需要查找 Content-Encoding: gzip
标头并创建 @987654327 @自己解压内容。
【讨论】:
【参考方案3】:我用我的一些设备进行了测试,HttpURLConnection 正在将Accept-Encoding: gzip
添加到标题中。
您是否尝试过 configuring Fiddler 为您的 Android 设备验证 http 标头?也许您的服务器不支持压缩。
【讨论】:
服务器确实进行了压缩,手动添加标头并使用 new GZipInputStream(conn.openInputStream()) 打开输入流是正确的。删除所有手动处理只会返回标准响应,并且标头缺少接受编码。【参考方案4】:我自己也经历过这种情况,并且发现如果我添加标头并手动使用 GZIPInputStream 就可以了。但是,我们手动设置了标题(我们必须添加一个自定义标题)。
Android 文档说“默认情况下,HttpURLConnection 的这种实现请求服务器使用 gzip 压缩。”所以我猜默认只有在你不手动设置标题的情况下才适用。
【讨论】:
以上是关于HttpURLConnection 不解压缩 Gzip的主要内容,如果未能解决你的问题,请参考以下文章