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

Node.js中PostgreSQL存储含无效UTF8字符数据报错的解决方案

问题描述

我使用Node.js搭配pg模块连接PostgreSQL数据库,通过ioredis获取数据:

let value = await redis.lrange('key', 0 ,-1 )

列表中的某一值为:

"{\"user_output_coding\":[\"\\nAman\\n\\n\",\"\\nxK\\u001d*\\xef\\xbf\\xbd\\n\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\nbhjs\\n\\n\",\"\\ndfgghgf\\ndese\\nrreteyt\\n\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\nghjhff\\ntyuyytu\\n\\n\",\"\\nbebzbh\\nasdf\\nasdf\\n\\n\",\"\\nfdgfdfgdfg\\ntrtyertgtrrgthtrt\\n\"]}"

执行value = JSON.parse(value)转换为对象:

value = { "user_output_coding" : [ "\nAman\n\n","\nxK\u001d*�\n\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\nbhjs\n\n","\ndfgghgf\ndese\nrreteyt\n\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\nghjhff\ntyuyytu\n\n","\nbebzbh\nasdf\nasdf\n\n","\nfdgfdfgdfg\ntrtyertgtrrgthtrt\n"]}

尝试将user_output_coding数组存入PostgreSQL的user_output text[] default '{}'字段时,出现错误:

invalid byte sequence for encoding "UTF8": 0x00                                        
    at Parser.parseErrorMessage (/home/codequotient/CQ_Main_Server/node_modules/pg-protocol/dist/parser.js:278:15)            
    at Parser.handlePacket (/home/codequotient/CQ_Main_Server/node_modules/pg-protocol/dist/parser.js:126:29)                 
    at Parser.parse (/home/codequotient/CQ_Main_Server/node_modules/pg-protocol/dist/parser.js:39:38)                          
    at Socket.<anonymous> (/home/codequotient/CQ_Main_Server/node_modules/pg-protocol/dist/index.js:10:42)                     
    at Socket.emit (events.js:315:20)               

试过使用pg工具类处理:

const postgreUtil = require('pg/lib/utils');
postgreUtil.prepareValue( value );

但问题未解决,求通用解决方案。

解决方案

错误核心是PostgreSQL的UTF8编码严格禁止空字节(0x00),同时数据中存在无效UTF8字符,需要先清理这些非法内容再存储。

1. 编写通用字符清理函数

创建函数过滤空字节和无效UTF8字符:

function cleanInvalidUtf8(str) {
  // 移除所有空字节(PostgreSQL UTF8绝对不允许)
  str = str.replace(/\x00/g, '');
  // 过滤无法被UTF8解析的控制字符、孤立代理对等无效内容
  return str.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF]/g, '')
            .replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])/g, '')
            .replace(/(?![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, '');
}

2. 批量清理数组元素

对user_output_coding数组的每个元素应用清理函数:

const cleanedOutput = value.user_output_coding.map(item => cleanInvalidUtf8(item));

3. 存入PostgreSQL

使用pg模块的参数化查询(自动处理类型转换,同时避免SQL注入):

const { Pool } = require('pg');
const pool = new Pool({ /* 你的数据库配置 */ });

async function saveCleanedData() {
  const client = await pool.connect();
  try {
    await client.query(
      'INSERT INTO your_table (user_output) VALUES ($1)',
      [cleanedOutput] // 直接传入清理后的数组,pg模块自动转为text[]类型
    );
  } finally {
    client.release();
  }
}

额外优化:Redis获取时提前处理

如果Redis中数据长期存在非法字符,可在获取后直接解析并清理:

let redisValues = await redis.lrange('key', 0, -1);
const processedValues = redisValues.map(raw => {
  const parsed = JSON.parse(raw);
  parsed.user_output_coding = parsed.user_output_coding.map(item => cleanInvalidUtf8(item));
  return parsed;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 13:20:28