java - 在 tomcat servlet 上使用服务器发送事件进行 gzip/deflate 压缩

标签 java tomcat gzip server-sent-events deflate

我正在使用服务器发送的事件来进行流式响应(文本/事件流)。我们想使用 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();

最佳答案

  1. 压缩流是二进制数据。它不得使用 response.getWriter() 打印。请改用 response.getOutputStream()

更新

Shiva Bhalla: Using the response.getOutputStream() with text/event-stream isn't doing proper streaming after the 1st chunk of response is displayed, the request is being failed at the browser.

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

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

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

    以上生成了不正确的存档。 Gzip 文件不能像那样连接。正确的代码应该执行以下操作:

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

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

关于java - 在 tomcat servlet 上使用服务器发送事件进行 gzip/deflate 压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52946239/

相关文章:

java - 如何按对象的多个属性进行排序 - linq4j

java - 在运行时选择实现

tomcat - 替换某些元素但保持剩余 XML 文档完好无损的样式表

ios - AFNetworking 启用 GZIP

ruby - 在 Heroku Cedar 上的 Rails 3.2 中,是否有一种标准的方式来提供预压缩的 Assets ?

java - 从其他用户获取图像

java - 用于查找树是否对称的代码中的错误

java - 信息 : TLD skipped. URI:<标记名称 URI> 已定义

spring - 仅在 IE8 中怎么可能出现 404 响应?

python - 如何确定 Python 中 gzip 文件的内容长度?