Java 从 json 属性解压缩 HTTP GZIP 内容
Java decompress HTTP GZIP content from json attribute
我们正在使用 packetbeat,这是一种网络数据包分析工具,用于捕获 http 请求和 http 响应。 Packebeat 以 json 格式保存此数据包事件。当服务器支持 gzip 压缩时,问题就来了,packetbeat 无法解压内容并直接将 gzip 内容保存为 json 属性。可以看到(注:json已经简化);
{
{
... ,
"content-type":"application/json;charset=UTF-8",
"transfer-encoding":"chunked",
"content-length":6347,
"x-application-context":"proxy-service:pre,native:8080",
"content-encoding":"gzip",
"connection":"keep-alive",
"date":"Mon, 18 Dec 2017 07:18:23 GMT"
},
"body": "\u001f\ufffd\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0003\ufffd]k\ufffd\u0014DZ\ufffd/\ufffdYI\ufffd#\ufffd*\ufffdo\ufffd\ufffd\ufffd\u0002\t\u0010^\ufffd\u001c\u000eE=\ufffd{\ufffdb\ufffd\ufffdE\ufffd\ufffdC\ufffd\ufffdf\ufffd,\ufffd\u003e\ufffd\ufffd\ufffd\u001ef\u001a\u0008\u0005\ufffd\ufffdg\ufffd\ufffd\ufffdYYU\ufffd\ufffd;\ufffdoN\ufffd\ufffd\ufffdg\ufffd\u0011UdK\ufffd\u0015\u0015\ufffdo\u000eH\ufffd\u000c\u0015Iq\ndC\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd ... "
}
我们正在考虑预处理数据包 json 文件以解压缩内容。有人可以告诉我使用 java 解压缩压缩 "body" json 属性需要什么吗?
在Java中你可以使用GZIPInputStream class来解码GZIP数据,我想你需要先把值变成一个ByteArrayInputStream。
您的数据已不可恢复地损坏。一般来说,我会建议使用 Base64 编码来传输打包到 JSON 中的二进制数据,但如果您喜欢试验,可以在 Binary Data in JSON String. Something better than Base64 中阅读可能的替代方案。
否则,理论上你可以只使用 String.getBytes()
的变体来获取字节数组,并将结果包装到提到的(在另一个答案中)流中:
byte bodyBytes[]=body.getBytes();
ByteArrayInputStream bais=new ByteArrayInputStream(bodyBytes);
GZipInputStream gis=new GZipInputStream(bais);
<do something with gis here, perhaps use an additional DataInputStream>
除了字符串(这通常不是一个好主意)之外,这是解压 gzip 压缩的字节数组的方式。
然而,有效的 gzip 数据以幻数 0x1F、0x8B 开头(再次参见 Wikipedia, or you can also dig up the actual specification). Your data starts with 0x1F (the \u001F
part), but continues with a \ufffd
Unicode character, which a replacement character (see Wikipedia)。
某些工具正在对二进制数据进行编码并且不喜欢 0x8B,很可能是因为它 >=0x80。如果你进一步阅读你的 JSON,里面有很多 \ufffd
-s,所有大于(或等于)0x80 的值都被这个替换了。因此,即使 JSON 内部支持原始二进制数据(但它不支持),目前的数据也无法恢复。
我们正在使用 packetbeat,这是一种网络数据包分析工具,用于捕获 http 请求和 http 响应。 Packebeat 以 json 格式保存此数据包事件。当服务器支持 gzip 压缩时,问题就来了,packetbeat 无法解压内容并直接将 gzip 内容保存为 json 属性。可以看到(注:json已经简化);
{
{
... ,
"content-type":"application/json;charset=UTF-8",
"transfer-encoding":"chunked",
"content-length":6347,
"x-application-context":"proxy-service:pre,native:8080",
"content-encoding":"gzip",
"connection":"keep-alive",
"date":"Mon, 18 Dec 2017 07:18:23 GMT"
},
"body": "\u001f\ufffd\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0003\ufffd]k\ufffd\u0014DZ\ufffd/\ufffdYI\ufffd#\ufffd*\ufffdo\ufffd\ufffd\ufffd\u0002\t\u0010^\ufffd\u001c\u000eE=\ufffd{\ufffdb\ufffd\ufffdE\ufffd\ufffdC\ufffd\ufffdf\ufffd,\ufffd\u003e\ufffd\ufffd\ufffd\u001ef\u001a\u0008\u0005\ufffd\ufffdg\ufffd\ufffd\ufffdYYU\ufffd\ufffd;\ufffdoN\ufffd\ufffd\ufffdg\ufffd\u0011UdK\ufffd\u0015\u0015\ufffdo\u000eH\ufffd\u000c\u0015Iq\ndC\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd ... "
}
我们正在考虑预处理数据包 json 文件以解压缩内容。有人可以告诉我使用 java 解压缩压缩 "body" json 属性需要什么吗?
在Java中你可以使用GZIPInputStream class来解码GZIP数据,我想你需要先把值变成一个ByteArrayInputStream。
您的数据已不可恢复地损坏。一般来说,我会建议使用 Base64 编码来传输打包到 JSON 中的二进制数据,但如果您喜欢试验,可以在 Binary Data in JSON String. Something better than Base64 中阅读可能的替代方案。
否则,理论上你可以只使用 String.getBytes()
的变体来获取字节数组,并将结果包装到提到的(在另一个答案中)流中:
byte bodyBytes[]=body.getBytes();
ByteArrayInputStream bais=new ByteArrayInputStream(bodyBytes);
GZipInputStream gis=new GZipInputStream(bais);
<do something with gis here, perhaps use an additional DataInputStream>
除了字符串(这通常不是一个好主意)之外,这是解压 gzip 压缩的字节数组的方式。
然而,有效的 gzip 数据以幻数 0x1F、0x8B 开头(再次参见 Wikipedia, or you can also dig up the actual specification). Your data starts with 0x1F (the \u001F
part), but continues with a \ufffd
Unicode character, which a replacement character (see Wikipedia)。
某些工具正在对二进制数据进行编码并且不喜欢 0x8B,很可能是因为它 >=0x80。如果你进一步阅读你的 JSON,里面有很多 \ufffd
-s,所有大于(或等于)0x80 的值都被这个替换了。因此,即使 JSON 内部支持原始二进制数据(但它不支持),目前的数据也无法恢复。