You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在浏览器压缩JSON并适配Node.js的bodyParser.json中间件?

嘿,我来帮你分析一下当前的实现问题,以及给出正确的做法~

现有实现的不合理之处

你的思路方向是对的(浏览器端压缩JSON再发送),但代码里有两个核心问题:

  1. 客户端的压缩结果使用方式不对:你写的compressGzip函数返回的是Response对象,但fetch的body参数需要的是Blob、ReadableStream、BufferSource这类可序列化的内容,直接把Response传进去是不符合要求的。
  2. 服务端未处理解压逻辑:bodyParser.json中间件默认只认明文的JSON字符串,它不会自动识别并解压Content-Encoding: gzip的请求体,所以后端会直接抛出JSON解析失败的错误。

正确的客户端实现

首先修正压缩函数,确保返回的是可以直接作为fetch body的类型(比如Blob),同时规范请求头的写法(HTTP头名称大小写不敏感,但按规范用Content-Encoding而非小写):

// 修正后的压缩函数:返回Blob类型,方便fetch使用
export async function compressGzip(inputJsonStr) {
  // inputJsonStr 需要是你要发送的JSON字符串(比如JSON.stringify(yourData))
  const stream = new Response(inputJsonStr).body.pipeThrough(new CompressionStream('gzip'));
  return new Response(stream).blob();
}

// React请求代码示例
async function sendCompressedData(url, data) {
  try {
    const jsonStr = JSON.stringify(data);
    const compressedBody = await compressGzip(jsonStr);
    
    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        'Content-Encoding': 'gzip' // 按HTTP规范写头名称
      },
      method: 'POST',
      body: compressedBody
    });
    
    return response.blob();
  } catch (err) {
    console.error('发送压缩数据失败:', err);
    throw err;
  }
}

正确的服务端实现

服务端需要先添加请求体解压中间件,把gzip压缩的二进制数据解压成明文JSON,再交给bodyParser.json处理。我们可以用Node.js内置的zlib模块来实现这个中间件:

const express = require('express');
const bodyParser = require('body-parser');
const zlib = require('zlib');
const app = express();

// 自定义gzip解压中间件
app.use((req, res, next) => {
  const contentEncoding = req.headers['content-encoding'];
  // 只有当请求头明确标记gzip压缩时,才进行解压
  if (contentEncoding && contentEncoding.includes('gzip')) {
    // 将请求流通过gunzip解压,拼接解压后的内容
    let rawBody = '';
    req.pipe(zlib.createGunzip())
      .on('data', (chunk) => rawBody += chunk.toString())
      .on('end', () => {
        req.body = rawBody;
        next();
      })
      .on('error', (err) => {
        console.error('解压请求体失败:', err);
        res.status(400).send('Invalid gzip data');
      });
  } else {
    // 没有压缩的请求,直接进入下一个中间件
    next();
  }
});

// 现在bodyParser可以正常解析解压后的明文JSON了
app.use(bodyParser.json({ limit: "10mb" }));

// 示例路由
app.post('/your-api', (req, res) => {
  console.log('解析后的JSON数据:', req.body);
  res.status(200).json({ message: '数据接收成功' });
});

app.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

额外注意事项

  1. 浏览器兼容性:CompressionStream是现代浏览器才支持的API(Chrome 80+、Firefox 113+),如果需要兼容旧浏览器,可以用第三方库如pako来实现gzip压缩。
  2. 异常处理:服务端要处理解压失败的情况(比如客户端发送的不是合法的gzip数据),避免服务器崩溃。
  3. 请求头校验:可以在服务端添加逻辑,校验Content-Encoding和Content-Type是否匹配,避免非法请求。

内容的提问来源于stack exchange,提问作者ESI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:07:50