如何使用Node将二进制对象存储在Redis中?

25

我正在尝试将一个二进制对象保存在Redis中,然后作为图像返回。

这是我用来保存数据的代码:

var buff=new Buffer(data.data,'base64');
client.set(key,new Buffer(data.data,'base64'));

以下是将数据导出的代码:

client.get(key,function(err,reply){
        var data = reply;
        response.writeHead(200, {"Content-Type": "image/png"});
        response.end(data,'binary');

});

数据的前几个字节似乎已经损坏了。魔数不正确。

进行了一些实验:

当我执行以下操作时:

var buff=new Buffer(data.data,'base64');
console.log(buff.toString('binary'));

我得到了这个:

0000000: c289 504e 470d 0a1a 0a00 0000 0d49 4844

当我执行以下操作时

 var buff=new Buffer(data.data,'base64');
 console.log(buff);

我得到了以下内容:

缓冲区 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00

我不确定 c2 是从哪里来的。


我没有以这种方式处理过图像,但是不是应该“解码”在base64中编码的内容吗? - Gntem
如果你 console.log(reply),你会得到什么?你能否详细说明一下将图像放入Redis的目的是什么?这不是存储大量二进制数据的最佳方式。 - loganfsmyth
数据以Base64格式传入,尝试保存二进制文件。 - SamFisher83
针对这个问题的后续:我也在尝试做基本相同的事情,但是当我使用get读取时,即使我写的内容相同,字符串长度也不同。 - Justin Thomas
7个回答

28

问题在于Node的Redis客户端默认将响应转换为JavaScript字符串。

我通过在创建客户端时将return_buffers选项设置为true来解决了这个问题。

var client = redis.createClient(7000, '127.0.0.1', {'return_buffers': true});

更多细节请参见此处


5

我遇到了类似的问题,在我的情况下,数据从Redis传输到Node.js时出现了损坏。在我的情况下,Node.js中的值被正确地存储,但当它进入节点时,它被转换为ASCII字符串。我可以使用以下行将其强制转换为缓冲区。

let file = await r.get(redis.commandOptions({ returnBuffers: true }), `zip/${req.params.taskId}`)

3

return_buffers存在的问题在于,当您不使用纯缓冲区数据时,您需要执行某些操作将其他缓冲区转换为字符串。虽然detect_buffers可能是一个选项,但它太不可靠了。

如果您不介意额外的计算周期,您也可以尝试:

// convert your buffer to hex string
client.set(key, mybuffer.toString('hex'));
// create a new buffer from hex string
client.get(key, function (err, val) {
   var bin = new Buffer(val, 'hex');
});

1
在大多数情况下,Base64是更好的选择,因为它会生成比十六进制更小的消息(代价是编码更昂贵)。 - Gajus

2

我无法弄清如何将二进制字符串存储。

这是我的解决方法:

其中data是base64字符串中的数据

client.set(count,data);

为了提供数据:

 client.get(last,function(err,reply){
   var data = reply;
   response.writeHead(200, {"Content-Type": "image/png"});
   var buff=new Buffer(data,'base64');
   response.end(buff);
});

这并不是理想的解决方案,因为每次都需要进行转换,但它似乎可以工作。

请注意,new Buffer()已被弃用。请使用:Buffer.from('some-data', 'base64'); - Yury Kozlov

1

这篇文章虽然有点旧,但是提供了最新的答案。正如另一个回答所述,所有的Node.js Redis库都会将数据返回为utf8字符串,因为这通常是人们需要的。像ioRedis这样的Node.js Redis库还提供了获取缓冲区数据的替代方法。例如,使用redis.getBuffer而不是redis.get


0

对我有效的方法是,如果是Buffer,则使用data.toString('binary')。还要确保不要将其重新解释为utf-8,而是作为binary


0

我在这个主题上找到了一篇文章,它解释了这样做的影响,我强烈建议在走这条路之前阅读它(无论使用什么编程语言)。

http://qnimate.com/storing-binary-data-in-redis/

总之,由于Redis是一个内存中的键/值存储,因此您最好不要将潜在较大的值(如图像)存储在Redis中,否则会迅速耗尽可用内存并降低Redis实例的性能。最好将文件的位置存储在Redis中,而不是存储文件本身。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接