Как вы управляете фрагментированными данными с помощью кодировки 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)
Выдает (также пробовал декодировать только данные после \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]
из-за идентификатора чанка в самом конце данных и с 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
:)