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".
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
});
this is my full solution which would read any base64 image format and save it in the proper format in the database:
UPDATE
I found this interesting link how to solve your problem in PHP. I think you forgot to replace
space
by+
as shown in the link.I took this circle from http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png as sample which looks like:
Next I put it through http://www.greywyvern.com/code/php/binary2base64 which returned me:
saved this string to
base64
which I read from in my code.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 imagepng from PHP page:
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.In Express you 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=PG and 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:app.js
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.
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.Here's an example:
Install it:
npm i ba64 -S
. Repo is on 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.
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.
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.
Update
As mentioned in the comments,
req.rawBody
is no longer a thing. If you are usingexpress
/connect
then you should use thebodyParser()
middleware and usereq.body
, and if you are doing this using standard Node then you need to aggregate the incomingdata
eventBuffer
objects and do this image data parsing in theend
callback.Easy way to convert base64 image into file and save as some random id or name.
Converting from file with base64 string to png image.
4 variants which works.