NodeJS: сохранение образа в кодировке base64 на диск
мое Экспресс-приложение получает кодированный base64 PNG из браузера (сгенерированный из canvas с помощью 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
});
6 ответов:
Я думаю, что вы конвертируете данные немного больше, чем нужно. После того, как вы создадите буфер с правильной кодировкой, вам просто нужно записать буфер в файл.
var base64Data = req.rawBody.replace(/^data:image\/png;base64,/, ""); require("fs").writeFile("out.png", base64Data, 'base64', function(err) { console.log(err); });новый буфер(..., 'base64') преобразует входную строку в буфер, который является просто массивом байтов, интерпретируя вход как строку в кодировке base64. Затем вы можете просто записать этот массив байтов в файл.
обновление
как уже упоминалось в комментариях,
req.rawBodyis больше ничего. Если вы используетеexpress/connectзатем вы должны использоватьbodyParser()middleware и использоватьreq.body, и если вы делаете это с помощью стандартного узла, то вам нужно агрегировать входящиеdataсобытиеBufferобъекты и сделать этот анализ данных изображения вendобратный.
Это мое полное решение, которое будет читать любой формат изображения в 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); }
обновление
я нашел это интересная ссылка, как решить вашу проблему в PHP. Я думаю, что вы забыли заменить
spaceby+как показано в ссылке.Я взял этот круг из 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 });Я круг назад, но самое смешное, что размер файла изменился :)...
конец
когда вы читаете назад изображение я думаю, что вам нужно настроить заголовки
Возьмем к примеру imagepng со страницы PHP:
<?php $im = imagecreatefrompng("test.png"); header('Content-Type: image/png'); imagepng($im); imagedestroy($im); ?>Я думаю, что вторая строка
header('Content-Type: image/png');, важно еще ваше изображение не будет отображается в браузере, но только куча двоичных данных отображается в браузере.на Экспресс вы бы просто использовать что-то вроде ниже. Я собираюсь показать ваш граватар, который находится по адресу 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приложение.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, которые являются частью URL-адресов данных, поэтому я в конечном итоге сделал небольшой модуль npm, чтобы сделать это в случае, если мне (или кому-то еще) нужно будет сделать это снова в будущем. Это называется ba64.
проще говоря, он принимает URL-адрес данных с изображением в кодировке Base64 и сохраняет изображение в вашей файловой системе. Он может сохранять синхронно или асинхронно. Он также имеет две вспомогательные функции, одна для получения расширения файла изображения, а другая для разделения Кодировка Base64 от
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.
простой способ конвертировать base64 изображение в файл и сохранить как некоторый случайный идентификатор или имя.
// 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 в png изображение.
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();

Comments