Сжатие ответа в контроллере Spring Boot и раздувание в JavaScript - PullRequest
0 голосов
/ 07 сентября 2018

Мы пытались использовать выходной поток Deflater и выходной поток GZIP на стороне сервера для сжатия ответа, а модуль Pako на стороне клиента - для его распаковки. Использование deflater приводит к ошибке консоли «необработанное исключение: недопустимое расстояние слишком далеко назад» в браузере, а использование 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'})));

1 Ответ

0 голосов
/ 08 сентября 2018

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

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

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

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

...