【问题标题】:gzip/deflate compression with Server Sent Events on tomcat servletgzip/deflate 压缩与 tomcat servlet 上的服务器发送事件
【发布时间】:2018-10-23 09:59:33
【问题描述】:

我正在使用服务器发送的事件进行流式响应(文本/事件流)。我们想使用 gzip 或 deflate 压缩来压缩响应,但浏览器显示:ERR_CONTENT_DECODING_FAILED。 相同的代码 -

response.setContentType("text/event-stream; charset=UTF-8");
response.addHeader("Connection", "keep-alive");
response.addHeader("Cache-Control", "no-cache, must-revalidate");
response.addHeader("Content-Encoding", "deflate");
PrintWriter writer = response.getWriter();
number = 10;
time = 100;
for (int i = 0; i < number; i++) {
  String resp = "data: " + "Some Response" + "\r\n";

  Deflater deflater = new Deflater(Deflater.DEFLATED);
  byte[] input = resp.getBytes("UTF-8");
  deflater.setInput(input);
  deflater.finish();
  byte[] output = new byte[1024];
  deflater.deflate(output);
  deflater.end();
  writer.write(new String(output, "UTF-8"));
  writer.flush();
  try {
    Thread.sleep(time);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}
String resp = "data: close\r\n";
Deflater deflater = new Deflater(Deflater.DEFLATED);
byte[] input = resp.getBytes("UTF-8");
deflater.setInput(input);
deflater.finish();
byte[] output = new byte[1024];
deflater.deflate(output);
deflater.end();
writer.write(new String(output, "UTF-8"));
writer.flush();

【问题讨论】:

    标签: java tomcat gzip server-sent-events deflate


    【解决方案1】:
    1. 压缩流是二进制数据。不得使用response.getWriter() 打印。请改用response.getOutputStream()

    更新

    Shiva Bhalla:在显示第一个响应块后,将 response.getOutputStream() 与 text/event-stream 一起使用并没有进行正确的流式传输,请求在浏览器中失败。

    1. 您必须使用单个 Deflater 实例压缩整个流。

      在您的代码中,您分别压缩每个片段。这相当于以下内容:

      • 您获取了一系列文本文件(01.txt、02.txt、...)。
      • 您将它们中的每一个压缩成一个 gzip 存档。 (01.txt.gz, 02.txt.gz, ...)
      • 您将档案连接成一个文件。

      以上产生了不正确的存档。 Gzip 文件不能这样连接。正确的代码应该做到以下几点:

      • 您获取了一系列文本文件(01.txt、02.txt、...)。
      • 您将文本文件连接成一个文件 (text.txt)。
      • 您将文件压缩为 gzip 存档。 (text.txt.gz)
    2. 我建议您使用java.util.zip.DeflaterOutputStream (1) 而不是直接使用Deflater。例如

      new DeflaterOutputStream(response.getOutputStream(), true);
      
    3. 小心引入BREACH 漏洞。

    【讨论】:

    • 在显示第一个响应块后,使用带有 text/event-stream 的 response.getOutputStream() 无法进行正确的流式传输,请求在浏览器中失败。
    • @Konstantin 您能否分享一个在 Java 中结合压缩实现服务器发送事件的参考?
    【解决方案2】:

    在连接器属性中添加“text/event-stream;charset=UTF-8,ms-stream;charset=UTF-8”作为“compressableMimeType”就可以了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-05
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 2010-12-24
      相关资源
      最近更新 更多