您如何使用 gzip 编码管理分块数据?我有一个服务器,它以下列方式发送数据:
HTTP/1.1 200 OK\r\n
...
Transfer-Encoding: chunked\r\n
Content-Encoding: gzip\r\n
\r\n
1f50\r\n\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xec}\xebr\xdb\xb8\xd2\xe0\xef\xb8\xea\xbc\x03\xa2\xcc\x17\xd9\xc7\xba\xfa\x1e\xc9r*\x93\xcbL\xf6\xcc\x9c\xcc7\xf1\x9c\xf9\xb6r\xb2.H ... L\x9aFs\xe7d\xe3\xff\x01\x00\x00\xff\xff\x03\x00H\x9c\xf6\xe93\x00\x01\x00\r\n0\r\n\r\n
我对此有几种不同的方法,但是我在这里忘记了一些东西。
data = b''
depleted = False
while not depleted:
depleted = True
for fd, event in poller.poll(2.0):
depleted = False
if event == select.EPOLLIN:
tmp = sock.recv(8192)
data += zlib.decompress(tmp, 15 + 32)
Gives(也尝试在\r\n\r\n
obv 之后仅解码数据):
zlib.error: Error -3 while decompressing data: incorrect header check
因此,我认为一旦以完整格式收到数据,就应该对数据进行解压缩..
...
if event == select.EPOLLIN:
data += sock.recv(8192)
data = zlib.decompress(data.split(b'\r\n\r\n',1)[1], 15 + 32)
同样的错误。data[:-7]
由于数据末尾的块ID以及其他各种组合,还尝试解压缩data[2:-7]
,但出现相同的错误。
我还gzip
通过以下方式尝试了该模块:
with gzip.GzipFile(fileobj=Bytes(data), 'rb') as fh:
fh.read()
但这给了我“不是压缩文件”。
即使将服务器收到的数据(标头+数据)记录到文件中,然后在端口 80 上创建一个服务器套接字,将数据(再次按原样)提供给浏览器,它也能完美呈现,因此数据是完好无损的。我拿了这些数据,去掉了标题(没有别的),然后在文件上尝试了 gzip:
感谢@mark-adler,我生成了以下代码来取消分块数据:
unchunked = b''
pos = 0
while pos <= len(data):
chunkLen = int(binascii.hexlify(data[pos:pos+2]), 16)
unchunked += data[pos+2:pos+2+chunkLen]
pos += 2+len('\r\n')+chunkLen
with gzip.GzipFile(fileobj=BytesIO(data[:-7])) as fh:
data = fh.read()
这产生OSError: CRC check failed 0x70a18ee9 != 0x5666e236
了更近一步的结果。简而言之,我根据这四个部分剪辑数据:
<chunk length o' X bytes>
\r\n
<chunk>
\r\n
我可能到了那里,但还不够近。
脚注:是的,套接字远非最佳,但它看起来是这样的,因为我认为我没有从套接字获取所有数据,所以我实现了一个巨大的超时并尝试使用depleted
:)进行故障保护