NodeJS: डिस्क में एक बेस 64-एन्कोडेड इमेज सेव करना


162

मेरा एक्सप्रेस ऐप ब्राउज़र से एक बेस 64-एनकोडेड 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
});

1
मैंने उत्तर दिया जो मुझे लगता है कि आपको पहली जगह में क्या चाहिए?)
अल्फ्रेड

जाहिर है कि यह वह नहीं है जो आपने मांगा था, लेकिन (मेरे मामले में) मुझे एहसास हुआ कि सबसे अच्छा तरीका यह था कि मैं अपने डेटाबेस में पूरी एनकोडेड स्ट्रिंग को स्टोर कर सकूं (आप हमेशा इसे इस्तेमाल करके लोड कर सकते हैं <img src="data:image/png;base64,..." />)। इस धागे के संदर्भ के रूप में उपयोग करने वाले अन्य लोगों के लिए विचार करने के लिए बस एक विकल्प।
JSideris

जवाबों:


324

मुझे लगता है कि आप डेटा को जरूरत से ज्यादा परिवर्तित कर रहे हैं। एक बार जब आप बफर को उचित एन्कोडिंग के साथ बनाते हैं, तो आपको फ़ाइल को बफर लिखने की आवश्यकता होती है।

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

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

नया बफ़र (..., 'बेस 64') इनपुट स्ट्रिंग को बफ़र में बदल देगा, जो कि बस बाइट्स की एक सरणी है, इनपुट को बेस 64 एनकोडेड स्ट्रिंग के रूप में व्याख्या करके। तब आप उस बाइट को फ़ाइल में लिख सकते हैं।

अपडेट करें

जैसा कि टिप्पणियों में बताया गया है, req.rawBodyअब कोई बात नहीं है। यदि आप उपयोग कर रहे हैं express/ connectतो आपको bodyParser()मिडिलवेयर और उपयोग करना चाहिए req.body, और यदि आप मानक नोड का उपयोग कर रहे हैं, तो आपको आने वाली dataईवेंट Bufferऑब्जेक्ट को एग्रीगेट करना होगा और endकॉलबैक में इस छवि डेटा पार्सिंग को करना होगा ।


2
इसके अलावा, आपके उदाहरण में राइटफाइल तर्क में थोड़ा टाइपो है: "बफरडेटा" -> "डेटाबफ़र"।
Mahemoff

@RJ। req.rawBodyइसमें अनुरोध डेटा शामिल है जो डेटा URL के रूप में एन्कोडेड है: developer.mozilla.org/en-US/docs/data_URIs । तो आपको बस आधार 64 डेटा प्राप्त करने के लिए शुरुआत भाग से अलग करना होगा।
loganfsmyth

2
यह उत्कृष्ट सामान है, धन्यवाद! भविष्य में इसे खोजने वालों के लिए, रॉबॉडी अब रीक की संपत्ति नहीं है। आपको डेटा प्राप्त करने के लिए एक्सप्रेस बॉडी पार्सर मिडलवेयर का उपयोग करना होगा।
DigitalDesignDj

10
var base64Data = req.rawBody.split (',') [1];
अंजा ईशमुखमीतोवा

@notgiorgi अपने मुद्दे को पुन: पेश करने के लिए पर्याप्त विवरण के साथ एक नया प्रश्न पूछने के लिए सबसे अच्छा है, और यह कहकर लिंक करें कि आप इसे काम नहीं कर सके।
loganfsmyth

22

यह मेरा पूर्ण समाधान है जो किसी भी बेस 64 छवि प्रारूप को पढ़ेगा और इसे डेटाबेस में उचित प्रारूप में बचाएगा:

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

यहाँ कोई भी मुझे जवाब देने के लिए ?? इस से सम्बन्धित??
iam

मैंने अभी आपका कोड संशोधित किया है fs.writeFile ("test.jpg", imageBuffer.data, function (इरेट) {json_response ['सफलता'] = true; res.json (json_response);}); छवि अपलोड की गई है लेकिन परिणाम मुझे पसंद नहीं आ रहा है। त्रुटि: 502 खराब गेटवे वास्तव में res.json में समस्या है, यह क्यों नहीं छपाई जा रही है ...
iam

18

अपडेट करें

मुझे यह दिलचस्प लिंक मिल गया कि PHP में आपकी समस्या को कैसे हल किया जाए । मुझे लगता है कि आप को बदलने के लिए भूल गया spaceद्वारा +के रूप में लिंक में दिखाया गया है।

मैंने इस सर्कल को 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

इस स्ट्रिंग को सहेजा गया है 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');, महत्वपूर्ण है कि आपकी छवि ब्राउज़र में प्रदर्शित नहीं होगी, लेकिन बस बाइनरी डेटा का एक गुच्छा ब्राउज़र को दिखाया गया है।

में एक्सप्रेस आप बस बस नीचे की तरह कुछ का प्रयोग करेंगे। मैं आपका 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। मैं केवल हेडर का अनुरोध करता हूं क्योंकि कर्ल बाइनरी सामान का एक गुच्छा प्रदर्शित करेगा (कंसोल पर Google क्रोम तुरंत डाउनलोड करने के लिए जाता है):

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

धन्यवाद अल्फ्रेड, लेकिन इस न्यूनतम परीक्षण मामले में, मैं सर्वर से कुछ भी वापस नहीं भेज रहा हूं। मैं बस सर्वर पर डिस्क पर फ़ाइल लिख रहा हूं, और ऐसा लगता है कि फ़ाइल ही एक वैध छवि नहीं है। मैं काफी हद तक निश्चित हूं कि बेस 64 सही है, लेकिन इसमें समस्या है कि इसे बाइनरी के रूप में लिखा जाए।
Mahemoff

1
क्षमा करें, मुझे गलत प्रश्न समझ में आया: $। मैं फिर से कोशिश करता हूँ।
अल्फ्रेड

1
अद्यतन के लिए धन्यवाद, लेकिन अंतरिक्ष प्रतिस्थापन मेरे लिए काम नहीं किया, और वास्तव में आवश्यक नहीं था जब मैंने लोगान के समाधान को लागू किया। संदर्भ के लिए, कैनवास मेरे परीक्षण के मामले में बहुत सरल है: var संदर्भ = कैनवस.गेट कॉन्टेक्स्ट ('2 डी'); संदर्भ.फिलस्टाइल = "# f89"; context.fillRect (50,50,100,100);
mahemoff

ठीक है क्योंकि मुझे छवि वापस मिल गई जब मैंने ऐसा किया, लेकिन कम से कम आपकी समस्या हल हो गई है: पी
अल्फ्रेड

दिलचस्प है, यह निश्चित नहीं है कि क्यों toString ("बाइनरी") ने आपके मामले में इसे गड़बड़ नहीं किया। किसी भी घटना में, बेस 6464 में वैसे भी स्वाभाविक रूप से प्रकट नहीं होने चाहिए, इसलिए प्रतिस्थापित होना चाहिए। यह मेरे द्वारा प्रदान किए गए उदाहरण के साथ है। (मैंने मैन्युअल रूप से डाली गई नई लाइनों के साथ एक संस्करण की कोशिश की, एमईएम कल्पना को पढ़ने के बाद लाइनों को 72 से अधिक वर्णों की आवश्यकता नहीं होती है, ज्यादातर व्यामोह से बाहर ... यह नई कहानियों के साथ या बिना काम करने के लिए निकलता है, जब तक कि स्ट्रींग ("बाइनरी") ) गिरा दिया जाता है।)
mahemoff

6

मुझे बेस 64 एनकोडेड चित्रों को भी सहेजना था जो डेटा URL का हिस्सा हैं, इसलिए मैंने इसे भविष्य में फिर से करने के लिए इसे (या किसी और को) करने के लिए एक छोटा npm मॉड्यूल बनाना समाप्त किया। इसे ba64 कहा जाता है ।

सीधे शब्दों में कहें, तो यह बेस64 एनकोडेड इमेज के साथ डेटा URL लेता है और इमेज को आपके फाइल सिस्टम में सेव करता है। यह सिंक्रोनाइज़ या एसिंक्रोनस रूप से सेव कर सकता है। इसमें दो सहायक कार्य भी हैं, एक छवि के फ़ाइल एक्सटेंशन को प्राप्त करने के लिए, और दूसरा बेस 64 एनकोडिंग को data:योजना के उपसर्ग से अलग करने के लिए ।

यहाँ एक उदाहरण है:

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:। रेपो GitHub पर है: https://github.com/HarryStevens/ba64

PS यह बाद में मुझे पता चला कि ba64 संभवतः मॉड्यूल का एक बुरा नाम है क्योंकि लोग मान सकते हैं कि यह Base64 एन्कोडिंग और डिकोडिंग करता है, जो यह नहीं करता है (बहुत सारे मॉड्यूल हैं जो पहले से ही ऐसा करते हैं)। ओह अच्छा।


2

यह मेरे लिए बस और पूरी तरह से किया।

स्कॉट रॉबिन्सन द्वारा उत्कृष्ट व्याख्या

छवि से बेस 64 स्ट्रिंग तक

let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');

बेस 64 स्ट्रिंग से छवि तक

let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);

1

बेस 64 इमेज को फाइल में बदलने का आसान तरीका और कुछ रैंडम आईडी या नाम के रूप में सेव करें।

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

बेस 64 स्ट्रिंग के साथ फाइल से पींग इमेज में बदलना।

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

1

फ़ाइलों को सहेजने के लिए नीचे फ़ंक्शन, बस अपनी बेस 64 फ़ाइल को पास करें, यह डीबी में इसे बचाने के लिए फ़ाइल नाम लौटाता है।

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

1
मेरे लिए काम किया। और इसका उपयोग किसी भी बेस 64 रूपांतरण के लिए किया जा सकता है। यह हर फ़ाइल को उदारतापूर्वक व्यवहार करता है। धन्यवाद!
गुइलहर्मे संपाओ

1

आप बेस -64-आईएमजी या बेस 64-टू-इमेज जैसी थर्ड पार्टी लाइब्रेरी का उपयोग कर सकते हैं ।

  1. बेस 64-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
  1. बेस 64 करने वाली छवि
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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.