NodeJS写入Base64图像文件

62

我的NodeJS服务器接收到一个经过base64编码的图片。

data:image/jpeg;base64,/9j/4QCcRXhpZgAASUkqAAgAAAA ... CiiigD//Z

接收到的数据应该以jpg格式保存。因此,我使用Buffer和FileSystemWriter:
var imageBuffer = new Buffer(data, 'base64'); //console = <Buffer 75 ab 5a 8a ...
fs.writeFile("test.jpg", imageBuffer, function(err) { //... });

fs.writeFile没有抛出错误。一个jpeg文件被保存了下来,但是我无法打开它。 图像查看器说:
File is damaged or too big.

原始文件大小为6kb,新文件为7kb。


10
你是否在尝试对数据进行 base64 解码之前切掉了开头的 data:image/jpeg;base64, - CBroe
1
不,我必须吗?我以为这些信息是由imageBuffer所需的。 - marcel
1
不,它是HTML中img、video标签所必需的,base64部分是在其后面的实际内容。 - Mustafa
啊,太棒了..它能正常工作 :)) - marcel
2
也许您可以回答这个问题,这样问题就不会在“未回答”类别中了吗? - hgoebl
6个回答

120

您需要从中删除URL元信息,即data:image/jpeg部分。(重申@CBroe的话)这是一个小函数,用于从输入字符串返回正确的信息。

var data = 'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA..kJggg==';

function decodeBase64Image(dataString) {
  var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
    response = {};

  if (matches.length !== 3) {
    return new Error('Invalid input string');
  }

  response.type = matches[1];
  response.data = new Buffer(matches[2], 'base64');

  return response;
}

var imageBuffer = decodeBase64Image(data);
console.log(imageBuffer);
// { type: 'image/jpeg',
//   data: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 b4 00 00 00 2b 08 06 00 00 00 d1 fd a2 a4 00 00 00 04 67 41 4d 41 00 00 af c8 37 05 8a e9 00 00 ...> }
然后您可以使用上述方法保存缓冲区。
fs.writeFile('test.jpg', imageBuffer.data, function(err) { ... });

1
谢谢您的回复,朱利安。我注意到您正在输入一个png base64字符串并输出一个jpg文件。这样可以吗?缓冲区会自动重新编码为新的文件类型吗?我在我的应用程序中也在做类似的事情,它似乎是有效的,但我想知道是否仍然存储了一个带有.jpg扩展名的png文件... - newshorts
2
通常情况下,文件扩展名不会影响图像的解析。操作系统通常会执行各种操作以自动更正“文件类型”。我已经修改了答案,以减少任何混淆。 - Julian Lannigan
嗨,这对我有用,但如果我想将其保存到数据库中怎么办?因为我尝试记录数据但没有打印任何内容。 - K.S
1
这个程序可以运行,但是我的图像查看器在尝试打开图像时会抛出一个错误。我收到了“无法加载文件,遇到了过早的文件结尾”的消息。我在某个地方读到过,这与解码不安全的URL有关。你有什么建议? - Grogu
3
由于new Buffer已被弃用,您可以使用Buffer.from(matches[2], 'base64'); - Aditya

45

另一种方法是在剔除元数据后,使用具有编码选项base64fs.writeFile

var image = 'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAA..kJggg==';

var data = image.replace(/^data:image\/\w+;base64,/, '');

fs.writeFile(fileName, data, {encoding: 'base64'}, function(err){
  //Finished
});

你在fileName参数中传递了什么? - Bandana Sahu
任何图像的文件名。例如:xyz.jpg - Muhammad Noman
我在互联网上寻找了很久。非常感谢! - Diego Fortes

3
我做了一些小改动,并采用了这种方法:
var imgData = req.body.image; // coming from client request
var base64Data = imgData.split(",")[1]; // split with `,`

require("fs").writeFile(
  Date.now() + "filename.jpeg",
  base64Data,
  "base64",
  function (err, data) {
    if (err) {
      console.log("err", err);
    }
    console.log(data, "data");
  }
);

您的文件将看起来像 1572341624757filename.jpeg

1

尝试这种简单的方法:

var imgData =
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA..kJggg==";
var base64Data = imgData.replace(/^data:image\/png;base64,/, "");

require("fs").writeFile(
  "out.png",
  base64Data,
  "base64",
  function (err, data) {
    if (err) {
      console.log("err", err);
    }
    console.log("success");
  }
);

重点关注:

  1. data:image/png;base 中有 png
  2. replace(/^data:image\/png; 中也有 png
  3. 文件名必须保存为 writeFile("out.png png

0

现在,你可以使用 Promise 来使代码更加简洁(从几个不同的答案中汲取最佳思路):

const fs = require("node:fs/promises");

(async () => {
  // sample (very small) base64 image
  const b64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII";
  await fs.writeFile("test.png", b64.split(",")[1], "base64");
})();

0
var crypto = require('crypto');
var seed = crypto.randomBytes(20);
var uniqueSHA1String = crypto.createHash('sha1').update(seed).digest('hex');
var imageTypeRegularExpression = /\/(.*?)$/;

var imageBuffer = this.decodeBase64Image(createSlideshowDto.base64);
var imageTypeDetected = imageBuffer.type.match(imageTypeRegularExpression);

var data = createSlideshowDto.base64.replace(
  /^data:image\/\w+;base64,/,
  '',
);
console.log(data);
fs.writeFile(
  `./files/base64-${uniqueSHA1String}.${imageTypeDetected[1]}}`,
  data,
  { encoding: 'base64' },
  function (err) {
    //Finished

    console.log(err);
  },
);

decodeBase64Image(dataString) { var matches = dataString.match(/^data:([A-Za-z-+/]+);base64,(.+)$/); var response: any = {};if (matches.length !== 3) { return new Error('无效的输入字符串'); } response.type = matches[1]; response.data = Buffer.from(matches[2], 'base64').toString('utf8'); console.log(response); return response; } - Ángel De La Cruz

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