Сжатие ответа в контроллере Spring Boot и раздувание в JavaScript

Мы пытались использовать поток вывода Deflater и поток вывода GZIP на стороне сервера для сжатия ответа и модуль Pako на стороне клиента для его распаковки. Использование дефлятора выдает ошибку консоли «неперехваченное исключение: недопустимое расстояние слишком далеко назад» в браузере, а использование gzip дает «неперехваченное исключение: недопустимый тип блока».

Из того, что я прочитал, браузер должен сам распаковать ответ, но с помощью «response.addHeader("Content-Encoding", "gzip");» не работает. Ошибки нет, ответ просто не имеет этого заголовка, когда браузер его получает.

Код дефлятора:

    private static String compress(String str)
    {
        try
        {
            final ByteArrayOutputStream out = new ByteArrayOutputStream();
            try
            {
                final DeflaterOutputStream def = new DeflaterOutputStream(out, new Deflater(Deflater.BEST_COMPRESSION, true));
                try
                {
                    def.write(str.getBytes());                    
                    return new String(Base64.encodeBase64(out.toByteArray()));
                }
                finally
                {def.close();}
            }
            finally
            {out.close();}
        }
        catch(IOException e)
        {
            LOGGER.warn("Failed to compress.");
        }
  return str;

Gzip-код.

    try
    {
        final ByteArrayOutputStream out = new ByteArrayOutputStream();

        try
        {    
            final GZIPOutputStream gzip = new GZIPOutputStream(out);
            try
            {gzip.write(str.getBytes());}
            finally
            {gzip.close();}

            return out.toString("UTF-8");
        }
        finally
        {out.close();}
    }
    catch(IOException e)
    {LOGGER.warn("Failed to compress.");}

    return str;
}

Звонок пако

LandAdditions.prototype.loadfields = function() {
    let me = this;

    me.loadingBanner().show();

    var url =
    "/rest/accounts/" + app.accountIdBox().val() + "/land_additions/fields";

  $.get(url)
    .done(function(data) {
      me.onLoadFields(JSON.parse(pako.inflateRaw(data, { to: 'string'})));

person Saphire    schedule 07.09.2018    source источник


Ответы (1)


Дефлятор (так в оригинале) создает необработанные данные дефляции, которые вы затем кодируете в Base-64. Ваш декодер pako сначала не декодирует кодировку Base-64, поэтому inflateRaw получает набор символов Base-64 вместо ожидаемого необработанного потока deflate.

GZIPOutputStream создает поток выкачивания, упакованный в gzip. inflateRaw ожидает необработанный поток дефляции, но вместо этого получает заголовок gzip, который он не ищет и интерпретирует как недопустимые данные дефляции.

Для первого нужно декодировать Base-64. Для второго нужно декодировать данные gzip, для чего у pako есть ungzip.

Кстати, вы не хотите кодировать двоичные данные как UTF-8. UTF-8 не может представлять все двоичные последовательности.

person Mark Adler    schedule 08.09.2018
comment
Спасибо за вашу помощь. Мы вернулись к GZIPOutputStream на стороне сервера, но когда мы используем pako.ungzip, мы получаем ошибку: «неверная проверка заголовка». - person Saphire; 13.09.2018