web-dev-qa-db-fra.com

NodeJS: enregistrement d'une image codée en base64 sur un disque

Mon application reçoit un fichier PNG codé en Base64 du navigateur (généré à partir de la toile avec toDataURL ()) et l'écrit dans un fichier. Mais le fichier n'est pas un fichier image valide et l'utilitaire "fichier" l'identifie simplement en tant que "données".

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

Je pense que vous convertissez les données un peu plus que nécessaire. Une fois que vous avez créé le tampon avec l'encodage approprié, il vous suffit d'écrire le tampon dans le fichier.

var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, "");

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

new Buffer (..., 'base64') convertira la chaîne d'entrée en un Buffer, qui n'est qu'un tableau d'octets, en interprétant l'entrée comme une chaîne codée en base64. Ensuite, vous pouvez simplement écrire ce tableau d'octets dans le fichier.

Mettre à jour

Comme mentionné dans les commentaires, req.rawBody n'est plus une chose. Si vous utilisez express/connect, vous devez utiliser le middleware bodyParser() et utiliser req.body. Si vous utilisez pour cela Node standard, vous devez agréger les objets entrants data événement Buffer et analyser les données d'image dans le rappel end.

246
loganfsmyth

voici ma solution complète qui lit tout format d'image base64 et l'enregistre au format approprié dans la base de données:

    // 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);
    }
18
Placeholder

METTRE À JOUR

J'ai trouvé ce lien intéressant sur la façon de résoudre votre problème en PHP }. Je pense que vous avez oublié de remplacer space par + comme indiqué dans le lien.

J'ai pris ce cercle de http://images-mediawiki-sites.thefullwiki.org/04/1/7/5/6204600836255205.png } comme exemple, qui ressemble à:

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

Ensuite, je l'ai mis à travers http://www.greywyvern.com/code/php/binary2base64 qui m'a renvoyé:

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

a sauvegardé cette chaîne sur base64 que j'ai lue dans mon code.

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

Je récupère un cercle, mais ce qui est drôle, c'est que la taille du fichier a changé:) ...

FIN

Lorsque vous relisez une image, vous devez configurer les en-têtes.

Prenons par exemple la _ { imagepng } _ de la page PHP:

<?php
$im = imagecreatefrompng("test.png");

header('Content-Type: image/png');

imagepng($im);
imagedestroy($im);
?>

Je pense que la deuxième ligne header('Content-Type: image/png');, est importante sinon votre image ne sera pas affichée dans le navigateur, mais seulement un tas de données binaires est montré au navigateur.

Dans Express , vous utiliseriez simplement quelque chose comme ci-dessous. Je vais afficher votre gravatar qui se trouve à l'adresse suivante: http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG C'est un fichier jpeg lorsque vous curl --head http://www.gravatar.com/avatar/cabf735ce7b8b4471ef46ea54f71832d?s=32&d=identicon&r=PG. Je ne demande que les en-têtes car sinon, curl affichera un tas d'éléments binaires (Google Chrome va immédiatement télécharger) à la console:

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
15
Alfred

Je devais également enregistrer des images codées en Base64 faisant partie d'URL de données. J'ai donc créé un petit module npm pour le faire au cas où moi-même (ou quelqu'un d'autre) aurais besoin de le refaire ultérieurement. Cela s'appelle ba64 .

En termes simples, il faut une URL de données avec une image codée en Base64 et l’enregistre sur votre système de fichiers. Il peut enregistrer de manière synchrone ou asynchrone. Il dispose également de deux fonctions d'assistance, l'une pour obtenir l'extension de fichier de l'image et l'autre pour séparer le codage Base64 du préfixe de schéma data:.

Voici un exemple:

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

Installez-le: npm i ba64 -S. Le repo est sur GitHub: https://github.com/HarryStevens/ba64 ​​ .

P.S. Plus tard, j’ai pensé que ba64 était probablement un mauvais nom pour le module car les gens pourraient supposer qu’il encodait et décodait en Base64, ce qui n’est pas le cas (beaucoup de modules le font déjà). Tant pis.

3
Harry Stevens

Un moyen facile de convertir base64 image en fichier et de le sauvegarder sous un identifiant ou un nom aléatoire.

// 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
1
Carlos

Conversion de fichier avec une chaîne base64 en image png.

4 variantes qui fonctionnent.

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();
1
Vladimir Buskin

Sous la fonction de sauvegarde des fichiers, transmettez simplement votre fichier base64, il renverra le nom de fichier, sauvegardez-le dans une base de données.

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

Blockquote

0
Shaik Matheen