NodeJS:将base64编码的图像保存到磁盘

我的快车应用程序正在从浏览器接收base64编码的PNG(从带有toDataURL()的canvas生成)并将其写入文件。 但该文件不是有效的图像文件,“文件”实用程序只是将其标识为“数据”。

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 }); 

我认为你正在转换数据比你需要的多一点。 一旦你创build了正确的编码缓冲区,你只需要将缓冲区写入文件。

 var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, ""); require("fs").writeFile("out.png", base64Data, 'base64', function(err) { console.log(err); }); 

新的Buffer(…,'base64')会将inputstring转换为一个Buffer,它只是一个字节数组,将input解释为一个base64编码的string。 然后,您可以将该字节数组写入文件。

更新

正如评论中提到的, req.rawBody不再是一件事情。 如果你正在使用express / connect那么你应该使用bodyParser()中间件,并使用req.body ,如果你正在使用标准的节点,那么你需要聚合传入的data事件Buffer对象,并做这个图像数据parsingendcallback。

这是我的完整解决scheme,它将读取任何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); } 

UPDATE

我发现这个有趣的链接如何解决你的问题在PHP中 。 我想你忘了用+replacespace ,如链接所示。

我把这个圈子从http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png作为样本,看起来像:;

http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png

接下来我把它通过http://www.greywyvern.com/code/php/binary2base64 ,它返回给我:

 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAAAAACPAi4CAAAAB3RJTUUH1QEHDxEhOnxCRgAAAAlwSFlzAAAK8AAACvABQqw0mAAAAXBJREFUeNrtV0FywzAIxJ3+K/pZyctKXqamji0htEik9qEHc3JkWC2LRPCS6Zh9HIy/AP4FwKf75iHEr6eU6Mt1WzIOFjFL7IFkYBx3zWBVkkeXAUCXwl1tvz2qdBLfJrzK7ixNUmVdTIAB8PMtxHgAsFNNkoExRKA+HocriOQAiC+1kShhACwSRGAEwPP96zYIoE8Pmph9qEWWKcCWRAfA/mkfJ0F6dSoA8KW3CRhn3ZHcW2is9VOsAgoqHblncAsyaCgcbqpUZQnWoGTcp/AnuwCoOUjhIvCvN59UBeoPZ/AYyLm3cWVAjxhpqREVaP0974iVwH51d4AVNaSC8TRNNYDQEFdlzDW9ob10YlvGQm0mQ+elSpcCCBtDgQD7cDFojdx7NIeHJkqi96cOGNkfZOroZsHtlPYoR7TOp3Vmfa5+49uoSSRyjfvc0A1kLx4KC6sNSeDieD1AWhrJLe0y+uy7b9GjP83l+m68AJ72AwSRPN5g7uwUAAAAAElFTkSuQmCC 

保存这个string到我从我的代码中读取的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 }); 

我得到一个回合,但有趣的是,文件大小已经改变:)…

结束

当你读回图像,我认为你需要设置标题

以PHP页面为例:

 <?php $im = imagecreatefrompng("test.png"); header('Content-Type: image/png'); imagepng($im); imagedestroy($im); ?> 

我想第二行header('Content-Type: image/png'); ,否则重要的是你的图像不会在浏览器中显示,而只是一堆二进制数据显示给浏览器。

在Express中,您只需使用类似下面的内容即可。 我将显示位于http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG的; gravatar,并且当您curl --head 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

 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 

简单的方法将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 

我还必须保存Base64编码的图像,这些图像是数据URL的一部分,所以我最终创build了一个小型的npm模块,以防万一我(或其他人)将来再次需要这样做。 这叫做ba64 。

简而言之,它需要一个带有Base64编码图像的数据URL,并将该图像保存到文件系统中。 它可以保存同步或asynchronous。 它还有两个辅助函数,一个用于获取图像的文件扩展名,另一个用于将Base64编码与data: scheme前缀分开。

这是一个例子:

 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 }); 

安装它: npm i ba64 -S 。 Repo在GitHub上: https : //github.com/HarryStevens/ba64 。

PS后来我发现,ba64可能是模块的坏名字,因为人们可能会认为它使用Base64编码和解码,而不是(有很多模块已经这样做了)。 好吧。