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
相关产品推荐
相关产品推荐

