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

Node.js使用Redis处理gzip二进制数据解压失败求助

解决方案

问题根源是Node Redis v4+ 默认会将Buffer类型的存储值自动转换为UTF-8字符串,导致压缩后的二进制数据因编码转换被损坏,最终解压时触发*“无效头部”*错误。

修复方案

在存储和读取数据时,明确指定encoding: 'buffer'选项,强制Redis以原始二进制格式处理数据:

  1. 修改存储逻辑:
// 原代码
// await redis.set('gzip', compressed)
// 修改后
await redis.set('gzip', compressed, { encoding: 'buffer' })
  1. 修改读取逻辑:
// 原代码
// const data = (await redis.get('gzip')) || Buffer.from('{}')
// 修改后
const data = (await redis.get('gzip', { encoding: 'buffer' })) || Buffer.from('{}')

完整修复后的代码

import { promisify } from 'node:util'
import { gzip } from 'node:zlib'
import { gunzip } from 'node:zlib'

import { redis } from '~/library/provider'

const asyncGzip = promisify(gzip)
const asyncGunzip = promisify(gunzip)

export async function handler() {
  try {
    await redis.connect()
  } catch (/* c8 ignore next */ error) {}

  const compressed = await asyncGzip(Buffer.from(JSON.stringify({ ok: true })))

  await redis.set('gzip', compressed, { encoding: 'buffer' }) // 新增编码选项

  console.log('>>> compressed', compressed)

  const data = (await redis.get('gzip', { encoding: 'buffer' })) || Buffer.from('{}') // 新增编码选项

  console.log('>>> data', data)

  const payload = await asyncGunzip(compressed) // OK!

  console.log('>>> payload', payload)

  const decompressed = await asyncGunzip(data) // 现在可以正常解压

  console.log('>>> decompressed', decompressed.toString())

  await redis.disconnect()

  return {
    statusCode: 200,
    body: JSON.stringify({ result: JSON.parse(decompressed.toString()) }),
  }
}

原理说明

gzip压缩后的二进制数据包含大量非UTF-8兼容的字节,Node Redis v4默认的字符串序列化会将这些字节转换为UTF-8字符串,这个过程会丢失或篡改原始二进制信息。当从Redis读取并转回Buffer时,数据已经损坏,自然无法通过gzip的头部校验。指定encoding: 'buffer'后,Redis会直接存储和返回原始Buffer,避免任何编码转换,保证压缩数据的完整性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:53:23