NodeJS base64 图像编码/解码不太工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8110294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NodeJS base64 image encoding/decoding not quite working
提问by Evan
I've been trying to handle saving images POSTed to nodeJS (and the express framework) to a database, and have been having some trouble. Ignoring all the web processing, I think that I've narrowed down the problem to the way base64 encoding is happening in node. I believe that the oversimplified example below should work, but the output image is always corrupted.
我一直在尝试将发布到 nodeJS(和 express 框架)的图像保存到数据库中,但遇到了一些麻烦。忽略所有的 Web 处理,我认为我已经将问题缩小到 node.js 中 base64 编码的发生方式。我相信下面过于简化的例子应该可以工作,但输出图像总是被破坏。
The example (1) loads in an image (2) saves a copy of if (image_orig) to confirm that node can read the file properly. This always works. (3) I take the image and base64 encode its contents, (4) then decode it. The final output image (image_decoded) is always corrupted.
示例 (1) 加载图像 (2) 保存 if ( image_orig)的副本以确认该节点可以正确读取文件。这总是有效的。(3) 我取图像并对它的内容进行 base64 编码,(4) 然后对其进行解码。最终输出图像 ( image_decoded) 始终损坏。
Help! (node.js 0.6.0 on OSX Lion)
帮助!(OSX Lion 上的 node.js 0.6.0)
console.log("starting");
process.chdir(__dirname);
var fs = require("fs");
var image_origial = "image.jpg";
fs.readFile(image_origial, function(err, original_data){
fs.writeFile('image_orig.jpg', original_data, function(err) {});
var base64Image = new Buffer(original_data, 'binary').toString('base64');
var decodedImage = new Buffer(base64Image, 'base64').toString('binary');
fs.writeFile('image_decoded.jpg', decodedImage, function(err) {});
});
回答by loganfsmyth
I think you are misunderstanding the usage of the encoding argument a bit. If you are going to specify encoding 'binary', then you need to do it consistently. But really you don't need it at all. You seem to be confusing the usage of Buffer vs binary strings.
我认为您有点误解了 encoding 参数的用法。如果要指定编码“二进制”,则需要始终如一地进行。但实际上你根本不需要它。您似乎混淆了 Buffer 与二进制字符串的用法。
// This tells node to load the file into a Buffer 'original_data' because you
// have not specified an encoding for the returned values. If you provided an
// encoding, then original_data would be a string with that encoding.
fs.readFile(image_origial, function(err, original_data){
// This tells node to take that buffer, and write it to the new filename.
// Again no encoding is provided, so it will assume a Buffer or utf8 string.
fs.writeFile('image_orig.jpg', original_data, function(err) {});
// This tells node to create a new buffer from the old buffer, which means
// it will iterate over original_data copying the bytes one at a time. But
// they will be identical buffers. It will ignore the 'binary' argument
// since the object you are passing isn't a string.
// Then it encodes the content of that Buffer to base64, which is fine.
var base64Image = new Buffer(original_data, 'binary').toString('base64');
// Here you decode the base64 to a buffer, which is fine, but then you
// convert the buffer into a string with encoding 'binary'. This means that
// it is a string object whose code points are bytes of the buffer.
var decodedImage = new Buffer(base64Image, 'base64').toString('binary');
// Here you try to write that String object to a file. Since the argument you
// have given is a string and you have not given an encoding argument for the
// write command, then it will assume that 'utf8' is the encoding. It will try to
// decode your binary string into a utf8 encoded buffer, and write that buffer.
// This will cause it to fail because that encoding conversion is wrong.
// Really through, 'binary' is just wrong to use. Buffers are already binary.
fs.writeFile('image_decoded.jpg', decodedImage, function(err) {});
});
This next example will work but is very inefficient because changing encodings all the time isn't needed, but I just want to show it to be clear. If you really DID want to have a specific encoding, you need to make sure you are consistent. Every one of those functions has an encoding argument.
下一个示例可以工作,但效率非常低,因为不需要一直更改编码,但我只想表明它是清晰的。如果你真的想要一个特定的编码,你需要确保你是一致的。这些函数中的每一个都有一个编码参数。
fs.readFile(image_origial, 'binary', function(err, original_data){
fs.writeFile('image_orig.jpg', original_data, 'binary', function(err) {});
var base64Image = new Buffer(original_data, 'binary').toString('base64');
var decodedImage = new Buffer(base64Image, 'base64').toString('binary');
fs.writeFile('image_decoded.jpg', decodedImage, 'binary', function(err) {});
});
This is the right way to do it. Keep everything as a Buffer, except when you make it base64.
这是正确的方法。将所有内容保留为缓冲区,除非您将其设为 base64。
fs.readFile(image_origial, function(err, original_data){
fs.writeFile('image_orig.jpg', original_data, function(err) {});
var base64Image = original_data.toString('base64');
var decodedImage = new Buffer(base64Image, 'base64');
fs.writeFile('image_decoded.jpg', decodedImage, function(err) {});
});
回答by simo
Slightly better solution will be to remove all mime types possible:
稍微好一点的解决方案是删除所有可能的 mime 类型:
var buff = new Buffer(req.body.imageFile
.replace(/^data:image\/(png|gif|jpeg);base64,/,''), 'base64');
fs.writeFile('/file/path/', buff, function (err) {
console.log('done');
});
This is addition to the @Herve's answer.
这是对@Herve 的回答的补充。

