imagen - base64 to image nodejs
NodeJS: guardar una imagen codificada en base64 en el disco (6)
La aplicación My Express está recibiendo un archivo PNG codificado en base64 del navegador (generado desde el lienzo con toDataURL ()) y lo está escribiendo en un archivo. Pero el archivo no es un archivo de imagen válido, y la utilidad "archivo" simplemente lo identifica como "datos".
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
});
ACTUALIZAR
Encontré este interesante enlace sobre cómo resolver su problema en PHP . Creo que olvidó reemplazar el space
por +
como se muestra en el enlace.
Tomé este círculo de http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png como muestra que se ve así:
Luego lo puse en http://www.greywyvern.com/code/php/binary2base64 que me devolvió:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAAAAACPAi4CAAAAB3RJTUUH1QEHDxEhOnxCRgAAAAlwSFlzAAAK8AAACvABQqw0mAAAAXBJREFUeNrtV0FywzAIxJ3+K/pZyctKXqamji0htEik9qEHc3JkWC2LRPCS6Zh9HIy/AP4FwKf75iHEr6eU6Mt1WzIOFjFL7IFkYBx3zWBVkkeXAUCXwl1tvz2qdBLfJrzK7ixNUmVdTIAB8PMtxHgAsFNNkoExRKA+HocriOQAiC+1kShhACwSRGAEwPP96zYIoE8Pmph9qEWWKcCWRAfA/mkfJ0F6dSoA8KW3CRhn3ZHcW2is9VOsAgoqHblncAsyaCgcbqpUZQnWoGTcp/AnuwCoOUjhIvCvN59UBeoPZ/AYyLm3cWVAjxhpqREVaP0974iVwH51d4AVNaSC8TRNNYDQEFdlzDW9ob10YlvGQm0mQ+elSpcCCBtDgQD7cDFojdx7NIeHJkqi96cOGNkfZOroZsHtlPYoR7TOp3Vmfa5+49uoSSRyjfvc0A1kLx4KC6sNSeDieD1AWhrJLe0y+uy7b9GjP83l+m68AJ72AwSRPN5g7uwUAAAAAElFTkSuQmCC
guardé esta cadena en base64
cual leí en mi código.
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
});
Obtengo un círculo hacia atrás, pero lo curioso es que el tamaño del archivo ha cambiado:) ...
FIN
Cuando vuelvas a leer la imagen, creo que debes configurar los encabezados
Tomemos como ejemplo imagepng desde la página PHP:
<?php
$im = imagecreatefrompng("test.png");
header(''Content-Type: image/png'');
imagepng($im);
imagedestroy($im);
?>
Creo que el header(''Content-Type: image/png'');
la segunda línea header(''Content-Type: image/png'');
, es importante que su imagen no se muestre en el navegador, pero solo se muestran un montón de datos binarios en el navegador.
En Express simplemente usarías algo como a continuación. Voy a mostrar su gravatar que se encuentra en http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG y es un archivo jpeg cuando curl --head http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG
. Solo solicito encabezados porque de lo contrario, Curl mostrará un montón de cosas binarias (Google Chrome se descarga inmediatamente) para la consola:
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
Conversión de archivo con cadena base64 a imagen png.
4 variantes que funcionan.
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();
Creo que está convirtiendo los datos un poco más de lo que necesita. Una vez que crea el búfer con la codificación adecuada, solo necesita escribir el búfer en el archivo.
var base64Data = req.rawBody.replace(/^data:image//png;base64,/, "");
require("fs").writeFile("out.png", base64Data, ''base64'', function(err) {
console.log(err);
});
new Buffer (..., ''base64'') convertirá la cadena de entrada en un Buffer, que es solo una matriz de bytes, interpretando la entrada como una cadena codificada en base64. Luego puedes escribir esa matriz de bytes en el archivo.
Actualizar
Como se mencionó en los comentarios, req.rawBody
ya no es una cosa. Si usa express
/ bodyParser()
debe usar el middleware bodyParser()
y usar req.body
, y si lo hace usando Node estándar, entonces necesita agregar los objetos Buffer
eventos de data
entrantes y analizar los datos de esta imagen en el end
devolución de llamada.
También tuve que guardar las imágenes codificadas en Base64 que forman parte de las URL de datos, así que terminé creando un pequeño módulo npm para hacerlo en caso de que yo (u otra persona) tuviera que volver a hacerlo en el futuro. Se llama ba64 .
En pocas palabras, toma una URL de datos con una imagen codificada en Base64 y guarda la imagen en su sistema de archivos. Puede guardar de forma síncrona o asíncrona. También tiene dos funciones auxiliares, una para obtener la extensión de archivo de la imagen, y la otra para separar la codificación Base64 de los data:
prefijo de esquema.
Aquí hay un ejemplo:
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
});
Instálelo: npm i ba64 -S
. Repo está en GitHub: https://github.com/HarryStevens/ba64 .
PD Más tarde me di cuenta de que ba64 es probablemente una mala denominación para el módulo, ya que las personas pueden suponer que tiene codificación y decodificación Base64, cosa que no ocurre (hay muchos módulos que ya lo hacen). Oh bien.
Una forma sencilla de convertir la imagen base64 en archivo y guardarla como una identificación o nombre aleatorio.
// 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
esta es mi solución completa que leería cualquier formato de imagen base64 y lo guardaría en el formato correcto en la base de datos:
// Save base64 image to disk
try
{
// Decoding base-64 image
// Source: http://.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);
}