Nodejs中mysql库的escape问题
Nodejs中mysql库的escape问题
我有一个buffer,我使用mysql提供的escape进行如下操作: con.escape( buffer.toString(‘binary’) ),通过这个将二进制数据存入数据库(mysql,字段数据类型为blob)。 现在的问题是: 从数据库内取这个数据,会比原始数据多十几个字节,什么原因,有人遇到过没,怎么解决的?
Node.js 中 MySQL 库的 escape 问题
问题描述
你有一个 Buffer 对象,希望将其转换为字符串并使用 mysql
库中的 escape
方法存储到 MySQL 数据库中。具体操作如下:
const escapedValue = con.escape(buffer.toString('binary'));
然后将 escapedValue
存储到一个 BLOB 类型的字段中。
但是当你从数据库中取出这个数据时,发现取出的数据比原始数据多了十几个字节。你怀疑是因为 escape
方法对数据进行了某种处理导致的。
原因分析
在 Node.js 中,mysql
库的 escape
方法会对传入的数据进行转义处理,以防止 SQL 注入攻击。对于字符串,它会在两端添加单引号,并对特殊字符进行转义。然而,当处理二进制数据时,这种转义可能会导致额外的字节被添加。
解决方案
为了避免这种额外字节的出现,你可以直接使用 Buffer 的 toJSON
方法或直接将 Buffer 转换为十六进制字符串,而不是先转换为二进制字符串。这样可以避免不必要的转义字符。
示例代码
假设你有一个 Buffer 对象 buffer
,你可以这样做:
// 将 Buffer 转换为十六进制字符串
const hexString = buffer.toString('hex');
// 直接存储十六进制字符串
const query = `INSERT INTO table_name (column_name) VALUES (?)`;
con.query(query, [hexString], (err, results) => {
if (err) throw err;
console.log("Data inserted successfully");
});
// 从数据库中读取数据
const selectQuery = 'SELECT column_name FROM table_name';
con.query(selectQuery, (err, results) => {
if (err) throw err;
const bufferFromDB = Buffer.from(results[0].column_name, 'hex');
console.log("Buffer from DB:", bufferFromDB);
});
在这个例子中,我们首先将 Buffer 对象转换为十六进制字符串,然后直接将该字符串存储到数据库中。从数据库中读取数据时,再将十六进制字符串转换回 Buffer 对象。
这种方法可以确保数据在存储和读取过程中保持一致,不会因为转义操作而增加额外的字节。
当你使用 mysql
模块中的 escape
方法将 Buffer 转换为字符串,并存储到 MySQL 数据库中时,可能会遇到数据长度增加的问题。这是因为 toString('binary')
将 Buffer 转换为了一个包含 ASCII 码的字符串,而这些 ASCII 码在存储和读取过程中可能会引入额外的字符。
原因
- 转换为字符串:
buffer.toString('binary')
将 Buffer 中的每个字节转换为对应的 ASCII 字符。 - 存储与读取:存储时,这些 ASCII 字符被正常存储;读取时,如果处理不当,可能会导致额外的字符被加入。
解决方案
最好的方式是直接将 Buffer 存储到数据库中,避免不必要的转换。MySQL 支持直接存储二进制数据,使用 BLOB
类型即可。
示例代码
const mysql = require('mysql');
// 创建连接
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
// 打开连接
con.connect(err => {
if (err) throw err;
console.log('Connected!');
// 示例 Buffer
const buffer = Buffer.from([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
// 直接插入 Buffer
const sqlInsert = 'INSERT INTO my_table (data) VALUES (?)';
con.query(sqlInsert, [buffer], (err, result) => {
if (err) throw err;
console.log('Data inserted');
});
// 查询 Buffer
const sqlSelect = 'SELECT data FROM my_table WHERE id = ?';
con.query(sqlSelect, [1], (err, result) => {
if (err) throw err;
console.log(result[0].data);
});
});
关键点
- 避免转换:不要使用
buffer.toString('binary')
进行转换。 - 直接存储:直接将 Buffer 作为参数传递给 SQL 语句,
mysql
模块会自动处理二进制数据的编码和解码。
通过这种方式,你可以确保从数据库读取的数据与原始数据完全一致,避免了额外字符的引入。