@tamerlanlarsanov

Как сжать и закодировать данные так, чтобы их можно было отправить в теле запроса на сервер?

У меня есть строка, изучив эту строку, я понял что это сжатые данные, о чём и говорится в теле запроса. Эту строку клиент отправляет на сервер в теле запроса. Как раскодировать эту строку я понял, но вот как сжать и закодировать обратно - нет. код очень простой, и понятный. В нём я раскодирую строку, а после кодирую теми же шагами обратно, но вот магия, на выходе я получаю уже другую строку, отличную от первоначальной. я пробовал разные уровни сжатия (0-9), но ничего не вышло. Почему False?

input = "H4sIAAAAAAAA_2SNvU7EMBAG32V7To7txMleB-JKWugsc-wllhI78k8iQLw7sgPVdauZHX0GFX5H7BHMumpnFoJzRIGw03u5muYwG4VovStIIaiT4OLE6gNDuE7GOZq1_SiEdwiZ2wf59Rjy8-vLdnm67Ref_e1t_BxrI2uTtMlp8qF2FlkxLcI1h0Au6RzpX_VStQ1X8li3iZY_IQbVDl3HWX-OOCBEmuf76ucXAAD__wEAAP__grfYVeYAAAA"
raw = input.replace("_", "/").replace("-", "+") + "="
raw = str.encode(raw)
raw = binascii.a2b_base64(raw)
raw = gzip.decompress(raw).decode()
raw = gzip.compress(raw.encode())
raw = binascii.b2a_base64(raw)
raw = raw.decode()
output = raw.replace("/", "_").replace("+", "-").replace("=", "")
print(input==output)
  • Вопрос задан
  • 125 просмотров
Пригласить эксперта
Ответы на вопрос 1
Vindicar
@Vindicar
RTFM!
У тебя различие появляется в том, что gzip.compress() даёт не тот же результат, что был подан в gzip.decompress().
Видимо, разные реализации алгоритма gzip. Но если данные успешно разжимаются, то не всё ли равно?

EDIT: я посмотрел инфу о заголовке Gzip. Создать идентичный заголовок несложно, но проблема идёт дальше: сами данные непохожи. Я раскопал, как получить "голый" deflate-поток без заголовков, и попытался сравнить его с тем, что идёт после gzip-заголовка в твоих данных. В твоём случае заголовок минималистичный, поэтому занимает всего 10 байт, а дальше идёт deflate-поток. Он успешно разжимается в те же данные, которые даёт gzip, так что я вроде не ошибся.

Но попытка перебора вариантов сжатия так, чтобы получить хоть что-то похожее, результатов не дала.
Вот мой код, увы, он выводит Match not found.
import binascii, gzip, zlib, sys

def deflate(data, compresslevel=9, strategy=0, wbits=zlib.MAX_WBITS, memlevel=zlib.DEF_MEM_LEVEL):
    compress = zlib.compressobj(
            compresslevel,        # level: 0-9
            zlib.DEFLATED,        # method: must be DEFLATED
            -wbits,               # window size in bits:
                                  #   -15..-8: negate, suppress header
                                  #   8..15: normal
                                  #   16..30: subtract 16, gzip header
            memlevel,             # mem level: 1..8/9
            strategy              # strategy:
                                  #   0 = Z_DEFAULT_STRATEGY
                                  #   1 = Z_FILTERED
                                  #   2 = Z_HUFFMAN_ONLY
                                  #   3 = Z_RLE
                                  #   4 = Z_FIXED
    )
    deflated = compress.compress(data)
    deflated += compress.flush()
    return deflated

def inflate(data):
    decompress = zlib.decompressobj(
            -zlib.MAX_WBITS  # see above
    )
    inflated = decompress.decompress(data)
    inflated += decompress.flush()
    return inflated


input_data = b"H4sIAAAAAAAA_2SNvU7EMBAG32V7To7txMleB-JKWugsc-wllhI78k8iQLw7sgPVdauZHX0GFX5H7BHMumpnFoJzRIGw03u5muYwG4VovStIIaiT4OLE6gNDuE7GOZq1_SiEdwiZ2wf59Rjy8-vLdnm67Ref_e1t_BxrI2uTtMlp8qF2FlkxLcI1h0Au6RzpX_VStQ1X8li3iZY_IQbVDl3HWX-OOCBEmuf76ucXAAD__wEAAP__grfYVeYAAAA"
gzipped_data = binascii.a2b_base64(input_data.replace(b"_", b"/").replace(b"-", b"+") + b"=")
raw_data = gzip.decompress(gzipped_data)
print('RAW', raw_data)

deflate_stream = gzipped_data[10:]
inflated = inflate(deflate_stream)
print('DEFLATED DATA', deflate_stream)
print('RESTORED DATA', inflated)
print('Restored data matches original:', inflated == raw_data)

for level in range(1, 10):
    for strategy in range(0, 5):
        for wbits in range(9, 16):
            for memlevel in range(1, 10):
                test = deflate(raw_data, level, strategy, wbits, memlevel)
                if deflate_stream.startswith(test) or test.startswith(deflate_stream):
                    print(level, strategy, wbits, memlevel)
                    sys.exit(0)
else:
    print('No match found')
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы