有个问题,请Nodejs高手解决

有个问题,请Nodejs高手解决

数据库:mysql node模块:mysql

我想压缩一段字符串,使用到了node的zlib,代码如下: var str = ‘[1,2,3,4,[1,2,3,4],6,7,8]’; zlib.gzip( str, function( err, buffer ){ db.update( table_name, { data : buffer.toString( ‘binary’ ) }, ‘id=10001’ fucntion( err, res ){} ); });

数据库的data字段数据类型我设置的为blob

然后我获取刚刚设置的数据: db.select( table_name, ‘id=10001’, function( err, res ) { var buf = res[0].data; //打印出从数据库取出的data,它的数据类型是buffer //我担心mysql库得到的buffer并不是我压缩时候的编码类型,所以我做了如下转化 var new_buf = new Buffer( buf.toString( ‘binary’ ), ‘binary’ ); //然后解压 zlib.unzip( new_buf, function( err, res ) { //这里就报错了 }) });

我看了下主要原因是,存进mysql的数据和取出来的数据不一样,不是说node_mysql已经支持binary的存储了吗,为什么还不一样,是不是底层在buffer数据了加了些东西,怎么解决这个问题,有人遇到过没


7 回复

针对你的问题,你可能遇到了一些关于数据编码和解码方面的细节问题。在Node.js中使用zlib模块进行字符串的压缩与解压时,确保编码的一致性是非常重要的。此外,MySQL的BLOB类型确实可以存储二进制数据,但你需要确保在读取和写入这些数据时正确处理它们。

以下是一个修复后的代码示例:

const zlib = require('zlib');
const mysql = require('mysql');

// 创建数据库连接
const db = mysql.createConnection({
  host: 'localhost',
  user: 'your_username',
  password: 'your_password',
  database: 'your_database'
});

// 压缩字符串并存储到数据库
var str = '[1,2,3,4,[1,2,3,4],6,7,8]';
zlib.gzip(str, function(err, buffer) {
  if (err) throw err;

  db.query('UPDATE table_name SET data = ? WHERE id = 10001', [buffer], function(err, res) {
    if (err) throw err;
    console.log("Data updated successfully.");
  });
});

// 从数据库中读取并解压数据
db.query('SELECT data FROM table_name WHERE id = 10001', function(err, results) {
  if (err) throw err;

  const buf = results[0].data;
  
  // 解压数据
  zlib.unzip(buf, function(err, decodedStr) {
    if (err) throw err;

    console.log(decodedStr.toString()); // 输出原始字符串
  });
});

在这个修正过的示例中,我们直接将zlib生成的Buffer对象存储到数据库中,而不是将其转换成二进制字符串。当从数据库中读取数据时,我们也直接使用该Buffer对象进行解压,而无需先将其转换为字符串再转换回来。这样可以避免编码转换带来的问题,并且确保数据在存储和检索过程中保持一致。


这是我在mysql模块上面的问题,里面问题错误描述更准确,https://github.com/felixge/node-mysql/issues/555#issuecomment-21480376

lz 的环境与这个人是否一致? 这个人说在这样的环境下完全没问题 mysql@2.0.0-alpha7 (and up) and it does the round-trip no problem on MySQL 5.1.

我正在找问题,呵

issue上给出的buff存储前后的数据

//Buffer 1f 8b 08 00 00 00 00 00 00 03 ab a8 00 01 00 6a 3e 40 d2 06 00 00 00

//Buffer 1f ef bf bd 08 00 00 00 00 00 00 03 ef bf bd ef bf bd 00 01 00 6a 3e 40 ef bf bd 06 00 00 00

这个结果,不是node-mysq掺入额外的数据,而是编码转换导致的,下面代码可重现前一个buffer是怎么转变为后一个buffer的。

var b='1f8b0800000000000003aba80001006a3e40d206000000';
b=new Buffer(b,'hex');
console.log('before:',b);
console.log('after:',new Buffer(b.toString('utf-8'),'utf-8'));

请确认自身代码没有在某个地方做了类似的编码转换

另外如果怀疑node-mysql出错,最好直接利用mysql的专门客户端软件导出blob字段的数据,来做前后对比。这比用自己未经测试的代码来作对比,有说服力的多。因为你没给出testcase,谁也不能确定错误究竟是来自node-mysql还是你自身的代码。

谢谢回答,终于找到问题了,我在node-mysql上还有一层封装,这里面将编码给转化了

根据你的描述,问题可能出在 Buffer 的编码处理上。在 Node.js 中,Buffer 对象本身没有特定的编码方式,而是字节数据的容器。你将 Buffer 转换成字符串时,可能会引入一些额外的信息或转换问题。

解决方案

你可以直接将 Buffer 存储到数据库中,而不需要将其转换为字符串。在读取时也直接使用 Buffer 对象进行解压操作。

以下是修改后的示例代码:

压缩并保存数据到数据库

const zlib = require('zlib');
const mysql = require('mysql');

// 创建数据库连接
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'test'
});

connection.connect();

var str = '[1,2,3,4,[1,2,3,4],6,7,8]';
zlib.gzip(str, (err, buffer) => {
  if (err) throw err;

  const query = connection.query(
    'UPDATE table_name SET data = ? WHERE id = 10001',
    [buffer],
    (err, res) => {
      if (err) throw err;
      console.log('Data updated successfully.');
    }
  );
});

从数据库读取并解压数据

connection.query('SELECT * FROM table_name WHERE id = 10001', (err, results) => {
  if (err) throw err;

  const compressedData = results[0].data;
  zlib.unzip(compressedData, (err, buffer) => {
    if (err) throw err;

    const originalString = buffer.toString();
    console.log(originalString);
  });
});

关键点解释

  1. 存储:直接使用 buffer 存储到数据库中,避免了不必要的字符串转换。
  2. 读取:直接使用 Buffer 对象进行解压,不需要进行字符串转换。

通过这种方式,可以确保 Buffer 数据在存储和读取过程中保持一致,避免因编码问题导致的错误。

回到顶部