NodeJS:将 base64 编码的图像保存到磁盘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6926016/
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: Saving a base64-encoded image to disk
提问by mahemoff
My Express app is receiving a base64-encoded PNG from the browser (generated from canvas with toDataURL() ) and writing it to a file. But the file isn't a valid image file, and the "file" utility simply identifies it as "data".
我的 Express 应用程序正在从浏览器接收 base64 编码的 PNG(使用 toDataURL() 从画布生成)并将其写入文件。但该文件不是有效的图像文件,“文件”实用程序只是将其标识为“数据”。
var body = req.rawBody,
base64Data = body.replace(/^data:image\/png;base64,/,""),
binaryData = new Buffer(base64Data, 'base64').toString('binary');
require("fs").writeFile("out.png", binaryData, "binary", function(err) {
console.log(err); // writes out file without error, but it's not a valid image
});
回答by loganfsmyth
I think you are converting the data a bit more than you need to. Once you create the buffer with the proper encoding, you just need to write the buffer to the file.
我认为您转换的数据比您需要的要多一些。一旦您使用正确的编码创建了缓冲区,您只需要将缓冲区写入文件。
var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, "");
require("fs").writeFile("out.png", base64Data, 'base64', function(err) {
console.log(err);
});
new Buffer(..., 'base64') will convert the input string to a Buffer, which is just an array of bytes, by interpreting the input as a base64 encoded string. Then you can just write that byte array to the file.
new Buffer(..., 'base64') 通过将输入解释为 base64 编码字符串,将输入字符串转换为 Buffer,它只是一个字节数组。然后您可以将该字节数组写入文件。
Update
更新
As mentioned in the comments, req.rawBodyis no longer a thing. If you are using express/connectthen you should use the bodyParser()middleware and use req.body, and if you are doing this using standard Node then you need to aggregate the incoming dataevent Bufferobjects and do this image data parsing in the endcallback.
正如评论中提到的,req.rawBody不再是一回事。如果您使用express/connect那么您应该使用bodyParser()中间件和 use req.body,如果您使用标准 Node 执行此操作,那么您需要聚合传入的data事件Buffer对象并在end回调中执行此图像数据解析。
回答by Placeholder
this is my full solution which would read any base64 image format and save it in the proper format in the database:
这是我的完整解决方案,它可以读取任何 base64 图像格式并将其以正确的格式保存在数据库中:
// Save base64 image to disk
try
{
// Decoding base-64 image
// Source: http://stackoverflow.com/questions/20267939/nodejs-write-base64-image-file
function decodeBase64Image(dataString)
{
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
var response = {};
if (matches.length !== 3)
{
return new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
}
// Regular expression for image type:
// This regular image extracts the "jpeg" from "image/jpeg"
var imageTypeRegularExpression = /\/(.*?)$/;
// Generate random string
var crypto = require('crypto');
var seed = crypto.randomBytes(20);
var uniqueSHA1String = crypto
.createHash('sha1')
.update(seed)
.digest('hex');
var base64Data = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAZABkAAD/4Q3zaHR0cDovL25zLmFkb2JlLmN...';
var imageBuffer = decodeBase64Image(base64Data);
var userUploadedFeedMessagesLocation = '../img/upload/feed/';
var uniqueRandomImageName = 'image-' + uniqueSHA1String;
// This variable is actually an array which has 5 values,
// The [1] value is the real image extension
var imageTypeDetected = imageBuffer
.type
.match(imageTypeRegularExpression);
var userUploadedImagePath = userUploadedFeedMessagesLocation +
uniqueRandomImageName +
'.' +
imageTypeDetected[1];
// Save decoded binary image to disk
try
{
require('fs').writeFile(userUploadedImagePath, imageBuffer.data,
function()
{
console.log('DEBUG - feed:message: Saved to disk image attached by user:', userUploadedImagePath);
});
}
catch(error)
{
console.log('ERROR:', error);
}
}
catch(error)
{
console.log('ERROR:', error);
}
回答by Alfred
UPDATE
更新
I found this interesting link how to solve your problem in PHP. I think you forgot to replace spaceby +as shown in the link.
我发现了这个有趣的链接 how to solve your problem in PHP。我想你忘记更换space的+,如图中的链接。
I took this circle from http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.pngas sample which looks like:
我从http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png 中取出这个圆圈作为示例,如下所示:


Next I put it through http://www.greywyvern.com/code/php/binary2base64which returned me:
接下来我把它通过http://www.greywyvern.com/code/php/binary2base64返回给我:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAAAAACPAi4CAAAAB3RJTUUH1QEHDxEhOnxCRgAAAAlwSFlzAAAK8AAACvABQqw0mAAAAXBJREFUeNrtV0FywzAIxJ3+K/pZyctKXqamji0htEik9qEHc3JkWC2LRPCS6Zh9HIy/AP4FwKf75iHEr6eU6Mt1WzIOFjFL7IFkYBx3zWBVkkeXAUCXwl1tvz2qdBLfJrzK7ixNUmVdTIAB8PMtxHgAsFNNkoExRKA+HocriOQAiC+1kShhACwSRGAEwPP96zYIoE8Pmph9qEWWKcCWRAfA/mkfJ0F6dSoA8KW3CRhn3ZHcW2is9VOsAgoqHblncAsyaCgcbqpUZQnWoGTcp/AnuwCoOUjhIvCvN59UBeoPZ/AYyLm3cWVAjxhpqREVaP0974iVwH51d4AVNaSC8TRNNYDQEFdlzDW9ob10YlvGQm0mQ+elSpcCCBtDgQD7cDFojdx7NIeHJkqi96cOGNkfZOroZsHtlPYoR7TOp3Vmfa5+49uoSSRyjfvc0A1kLx4KC6sNSeDieD1AWhrJLe0y+uy7b9GjP83l+m68AJ72AwSRPN5g7uwUAAAAAElFTkSuQmCC
saved this string to base64which I read from in my code.
保存了base64我在代码中读取的这个字符串。
var fs = require('fs'),
data = fs.readFileSync('base64', 'utf8'),
base64Data,
binaryData;
base64Data = data.replace(/^data:image\/png;base64,/, "");
base64Data += base64Data.replace('+', ' ');
binaryData = new Buffer(base64Data, 'base64').toString('binary');
fs.writeFile("out.png", binaryData, "binary", function (err) {
console.log(err); // writes out file without error, but it's not a valid image
});
I get a circle back, but the funny thing is that the filesize has changed :)...
我得到了一个圆圈,但有趣的是文件大小已经改变了:)...
END
结尾
When you read back image I think you need to setup headers
当您读回图像时,我认为您需要设置标题
Take for example imagepngfrom PHP page:
以PHP 页面中的imagepng为例:
<?php
$im = imagecreatefrompng("test.png");
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>
I think the second line header('Content-Type: image/png');, is important else your image will not be displayed in browser, but just a bunch of binary data is shown to browser.
我认为第二行header('Content-Type: image/png');很重要,否则您的图像将不会显示在浏览器中,而只会向浏览器显示一堆二进制数据。
In Expressyou would simply just use something like below. I am going to display your gravatar which is located at http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PGand is a jpeg file when you curl --head http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG. I only request headers because else curl will display a bunch of binary stuff(Google Chrome immediately goes to download) to console:
在Express 中,您只需使用如下所示的内容即可。我将显示您的 gravatar,它位于http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG并且是一个 jpeg 文件,当您使用curl --head http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG. 我只请求标头,因为否则 curl 会向控制台显示一堆二进制内容(Google Chrome 会立即下载):
curl --head "http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG"
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 03 Aug 2011 12:11:25 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Mon, 04 Oct 2010 11:54:22 GMT
Content-Disposition: inline; filename="cabf735ce7b8b4471ef46ea54f71832d.jpeg"
Access-Control-Allow-Origin: *
Content-Length: 1258
X-Varnish: 2356636561 2352219240
Via: 1.1 varnish
Expires: Wed, 03 Aug 2011 12:16:25 GMT
Cache-Control: max-age=300
Source-Age: 1482
$ mkdir -p ~/tmp/6922728
$ cd ~/tmp/6922728/
$ touch app.js
app.js
应用程序.js
var app = require('express').createServer();
app.get('/', function (req, res) {
res.contentType('image/jpeg');
res.sendfile('cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG');
});
app.get('/binary', function (req, res) {
res.sendfile('cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG');
});
app.listen(3000);
$ wget "http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG"
$ node app.js
回答by Harry Stevens
I also had to save Base64 encoded images that are part of data URLs, so I ended up making a small npm module to do it in case I (or someone else) needed to do it again in the future. It's called ba64.
我还必须保存作为数据 URL 一部分的 Base64 编码图像,所以我最终制作了一个小的 npm 模块来完成它,以防我(或其他人)将来需要再次这样做。它被称为ba64。
Simply put, it takes a data URL with a Base64 encoded image and saves the image to your file system. It can save synchronously or asynchronously. It also has two helper functions, one to get the file extension of the image, and the other to separate the Base64 encoding from the data:scheme prefix.
简而言之,它采用带有 Base64 编码图像的数据 URL,并将图像保存到您的文件系统。它可以同步或异步保存。它还具有两个辅助函数,一个用于获取图像的文件扩展名,另一个用于将 Base64 编码与data:方案前缀分开。
Here's an example:
下面是一个例子:
var ba64 = require("ba64"),
data_url = "data:image/jpeg;base64,[Base64 encoded image goes here]";
// Save the image synchronously.
ba64.writeImageSync("myimage", data_url); // Saves myimage.jpeg.
// Or save the image asynchronously.
ba64.writeImage("myimage", data_url, function(err){
if (err) throw err;
console.log("Image saved successfully");
// do stuff
});
Install it: npm i ba64 -S. Repo is on GitHub: https://github.com/HarryStevens/ba64.
安装它:npm i ba64 -S。回购在 GitHub 上:https: //github.com/HarryStevens/ba64。
P.S. It occurred to me later that ba64 is probably a bad name for the module since people may assume it does Base64 encoding and decoding, which it doesn't (there are lots of modules that already do that). Oh well.
PS 后来我想到 ba64 对模块来说可能是一个坏名字,因为人们可能认为它进行 Base64 编码和解码,但事实并非如此(有很多模块已经这样做了)。那好吧。
回答by dovk
This did it for me simply and perfectly.
这对我来说简单而完美。
Excellent explanation by Scott Robinson
From image to base64 string
从图像到 base64 字符串
let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');
From base64 string to image
从 base64 字符串到图像
let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);
回答by ns16
You can use a third-party library like base64-imgor base64-to-image.
您可以使用第三方库,如base64-img或base64-to-image。
- base64-img
- base64-img
const base64Img = require('base64-img');
const data = 'data:image/png;base64,...';
const destpath = 'dir/to/save/image';
const filename = 'some-filename';
base64Img.img(data, destpath, filename, (err, filepath) => {}); // Asynchronous using
const filepath = base64Img.imgSync(data, destpath, filename); // Synchronous using
- base64-to-image
- base64 到图像
const base64ToImage = require('base64-to-image');
const base64Str = 'data:image/png;base64,...';
const path = 'dir/to/save/image/'; // Add trailing slash
const optionalObj = { fileName: 'some-filename', type: 'png' };
const { imageType, fileName } = base64ToImage(base64Str, path, optionalObj); // Only synchronous using
回答by Vladimir Buskin
Converting from file with base64 string to png image.
将带有 base64 字符串的文件转换为 png 图像。
4 variants which works.
4 个有效的变体。
var {promisify} = require('util');
var fs = require("fs");
var readFile = promisify(fs.readFile)
var writeFile = promisify(fs.writeFile)
async function run () {
// variant 1
var d = await readFile('./1.txt', 'utf8')
await writeFile("./1.png", d, 'base64')
// variant 2
var d = await readFile('./2.txt', 'utf8')
var dd = new Buffer(d, 'base64')
await writeFile("./2.png", dd)
// variant 3
var d = await readFile('./3.txt')
await writeFile("./3.png", d.toString('utf8'), 'base64')
// variant 4
var d = await readFile('./4.txt')
var dd = new Buffer(d.toString('utf8'), 'base64')
await writeFile("./4.png", dd)
}
run();
回答by Shaik Matheen
Below function to save files, just pass your base64 file, it return filename save it in DB.
在保存文件的功能下面,只需传递您的 base64 文件,它就会返回文件名,将其保存在数据库中。
import fs from 'fs';
const uuid = require('uuid/v1');
/*Download the base64 image in the server and returns the filename and path of image.*/
function saveImage(baseImage) {
/*path of the folder where your project is saved. (In my case i got it from config file, root path of project).*/
const uploadPath = "/home/documents/project";
//path of folder where you want to save the image.
const localPath = `${uploadPath}/uploads/images/`;
//Find extension of file
const ext = baseImage.substring(baseImage.indexOf("/")+1, baseImage.indexOf(";base64"));
const fileType = baseImage.substring("data:".length,baseImage.indexOf("/"));
//Forming regex to extract base64 data of file.
const regex = new RegExp(`^data:${fileType}\/${ext};base64,`, 'gi');
//Extract base64 data.
const base64Data = baseImage.replace(regex, "");
const filename = `${uuid()}.${ext}`;
//Check that if directory is present or not.
if(!fs.existsSync(`${uploadPath}/uploads/`)) {
fs.mkdirSync(`${uploadPath}/uploads/`);
}
if (!fs.existsSync(localPath)) {
fs.mkdirSync(localPath);
}
fs.writeFileSync(localPath+filename, base64Data, 'base64');
return filename;
}
回答by Carlos
Easy way to convert base64image into file and save as some random id or name.
将base64图像转换为文件并另存为一些随机 ID 或名称的简单方法。
// to create some random id or name for your image name
const imgname = new Date().getTime().toString();
// to declare some path to store your converted image
const path = yourpath.png
// image takes from body which you uploaded
const imgdata = req.body.image;
// to convert base64 format into random filename
const base64Data = imgdata.replace(/^data:([A-Za-z-+/]+);base64,/, '');
fs.writeFile(path, base64Data, 'base64', (err) => {
console.log(err);
});
// assigning converted image into your database
req.body.coverImage = imgname

