如何使用来自 java 服务器的 XMLHttpRequest 接收压缩的 JSON 数据

How to receive compressed JSON data using XMLHttpRequest from a java server

我正在使用 XMLHttpRequest 请求和解析 json 数据。使用嵌入式码头 9 的 java 8 服务器接收请求和 returns 数据。代码如下所示,第一个块中的客户端 java 脚本和第二个块中的服务器端 java 代码。

var http = new XMLHttpRequest();
http.onreadystatechange=function() {
  if (this.readyState == 4) {
    if (this.status == 200) {
      data = JSON.parse(this.responseText);
    }
  }
};
http.open("GET", "/mydata", true);
http.send();

 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

  response.setContentType("application/json");
  response.setStatus(Response.SC_OK);
  PrintWriter pw = response.getWriter();
  pw.write(myDataInJsonStringFormat);
  pw.close();
  baseRequest.setHandled(true);
}

问题是如何修改上述代码以从 java 发送压缩的 json 数据,然后使用 XMLHttpRequest 解压缩数据?

我宁愿不使用任何额外的客户端或服务器端库,而不是我已经在使用的库。

将 Eclipse Jetty GzipHandler 添加到服务器处理程序树中自定义处理程序代码之前的位置。

这将执行 2 个任务:

  • 它将解压缩传入的压缩请求正文内容
  • 它将压缩传出的响应正文内容

只需确保在 GzipHandler 上配置包含的 MIME 类型列表,以允许 application/json 对响应正文内容进行处理。

您可以使用base64 来传输数据。其中有两个函数分别对base64字符串进行解码和编码:atob()和btoa()。使用 java.

搜索如何执行此操作

在这种情况下,相同的数据集被重复提供给客户端。 json 文本字符串被转换为 gzip 字节数组,而不是添加码头处理程序:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(bos);
OutputStreamWriter osw = new OutputStreamWriter(gzip, StandardCharsets.UTF_8);
osw.write(myDataInJsonStringFormat);
osw.close();

compressedJsonData = bos.toByteArray();

然后数据由码头处理程序返回给 java 客户端:

public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

  response.setContentType("application/json");
  response.setHeader("Content-Encoding", "gzip");
  response.setContentLength(compressedJsonData .length);

  response.setStatus(Response.SC_OK);

  response.getOutputStream().write(compressedJsonData );
  response.getOutputStream().close();

  baseRequest.setHandled(true);
}

在客户端的 XMLHttpRequest java 脚本代码中,无需更改。浏览器(在 Edge、IE11、Chrome 上验证)会自动解压缩 json 并将其转换回文本,然后再传递给 this.responseText :

var http = new XMLHttpRequest();
http.onreadystatechange=function() {
  if (this.readyState == 4) {
    if (this.status == 200) {
      data = JSON.parse(this.responseText);
    }
  }
};
http.open("GET", "/mydata", true);
http.send();

我还添加了一个进度条来向客户端显示已经下载了多少数据。为此,压缩前的长度被保存并添加为服务器端的自定义 http header

response.setHeader("Uncompressed-Length", myDataInJsonStringFormat.length + "");

在客户端,当 readyState = = 2 和一个进度处理程序设置如下:

    http.onprogress = function(event) {
      var percentComplete = Math.round((event.loaded/estimatedLength) * 100);
      progressMessage = Math.round(event.loaded/1000) + "KB downloaded and uncompressed, " + percentComplete + "%";
    };