- How to save a base64 image to user’s disk using javascript?
- Method 1: Using the URL.createObjectURL() Method
- Method 2: Using the FileSaver.js Library
- Step 1: Include FileSaver.js Library
- Step 2: Convert Base64 Image to Blob
- Step 3: Save Blob to User’s Disk
- Step 4: Call the Function
- Method 3: Using the canvas.toBlob() Method
- Blob
- Blob как URL
- Blob to base64
- Изображение в Blob
- Из Blob в ArrayBuffer
- Итого
How to save a base64 image to user’s disk using javascript?
Base64 is a widely used encoding format to represent binary data in a text format. In JavaScript, it is often used to embed images and other multimedia in web pages. However, when it comes to saving the base64 data as an image file on the user’s disk, it can sometimes be challenging to do so. Here are a few methods to save a base64 image to the user’s disk using JavaScript:
Method 1: Using the URL.createObjectURL() Method
To save a base64 image to user’s disk using JavaScript, you can use the URL.createObjectURL() method. Here are the steps to do it:
const base64Image = 'data:image/png;base64,iVBORw0KG. '; const blob = new Blob([base64Image], type: 'image/png' >);
const url = URL.createObjectURL(blob);
const link = document.createElement('a'); link.href = url;
const base64Image = 'data:image/png;base64,iVBORw0KG. '; const blob = new Blob([base64Image], type: 'image/png' >); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = 'image.png'; link.click();
Note that the URL.createObjectURL() method creates a temporary URL that points to the Blob object. It’s important to revoke the URL after the download is complete to free up memory:
Method 2: Using the FileSaver.js Library
Here is a step-by-step guide on how to save a base64 image to the user’s disk using the FileSaver.js library.
Step 1: Include FileSaver.js Library
Include the FileSaver.js library in your HTML file using the following code:
script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"> script>
Step 2: Convert Base64 Image to Blob
Convert the base64 image to a Blob object using the following code:
function b64toBlob(b64Data, contentType, sliceSize) contentType = contentType || ''; sliceSize = sliceSize || 512; const byteCharacters = atob(b64Data); const byteArrays = []; for (let offset = 0; offset byteCharacters.length; offset += sliceSize) const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for (let i = 0; i slice.length; i++) byteNumbers[i] = slice.charCodeAt(i); > const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); > const blob = new Blob(byteArrays, type: contentType >); return blob; >
Step 3: Save Blob to User’s Disk
Save the Blob object to the user’s disk using the following code:
function saveImageToDisk(fileUrl, fileName) const xhr = new XMLHttpRequest(); xhr.open('GET', fileUrl, true); xhr.responseType = 'blob'; xhr.onload = function () if (xhr.status === 200) const blob = xhr.response; saveBlobToDisk(blob, fileName); > >; xhr.send(); > function saveBlobToDisk(blob, fileName) saveAs(blob, fileName); >
Step 4: Call the Function
Call the saveImageToDisk function with the base64 image and the desired file name as parameters.
const base64Image = 'data:image/png;base64,iVBORw0KG. '; const fileName = 'image.png'; saveImageToDisk(base64Image, fileName);
That’s it! The base64 image will be saved to the user’s disk with the specified file name.
Method 3: Using the canvas.toBlob() Method
To save a base64 image to the user’s disk using JavaScript, we can use the canvas.toBlob() method. Here are the steps to achieve this:
const img = new Image(); img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA. ';
img.onload = function() // Image has loaded >;
const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height;
const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0);
canvas.toBlob(function(blob) // Blob has been created >, 'image/png');
The first argument to canvas.toBlob() is a callback function that will be called with the Blob as its argument. The second argument specifies the MIME type of the image.
const img = new Image(); img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA. '; img.onload = function() const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); canvas.toBlob(function(blob) // Save the blob to disk using FileSaver.js or other library >, 'image/png'); >;
Note that you’ll need to use a library like FileSaver.js to actually save the Blob to disk.
Blob
ArrayBuffer и бинарные массивы являются частью ECMA-стандарта и, соответственно, частью JavaScript.
Кроме того, в браузере имеются дополнительные высокоуровневые объекты, описанные в File API.
Объект Blob состоит из необязательной строки type (обычно MIME-тип) и blobParts – последовательности других объектов Blob , строк и BufferSource .
Благодаря type мы можем загружать и скачивать Blob-объекты, где type естественно становится Content-Type в сетевых запросах.
Конструктор имеет следующий синтаксис:
new Blob(blobParts, options);
- blobParts – массив значений Blob / BufferSource / String .
- options – необязательный объект с дополнительными настройками:
- type – тип объекта, обычно MIME-тип, например. image/png ,
- endings – если указан, то окончания строк создаваемого Blob будут изменены в соответствии с текущей операционной системой ( \r\n или \n ). По умолчанию «transparent» (ничего не делать), но также может быть «native» (изменять).
// создадим Blob из строки let blob = new Blob(["…"], ); // обратите внимание: первый аргумент должен быть массивом [. ]
// создадим Blob из типизированного массива и строк let hello = new Uint8Array([72, 101, 108, 108, 111]); // "hello" в бинарной форме let blob = new Blob([hello, ' ', 'world'], );
Мы можем получить срез Blob, используя:
blob.slice([byteStart], [byteEnd], [contentType]);
- byteStart – стартовая позиция байта, по умолчанию 0.
- byteEnd – последний байт, по умолчанию до конца.
- contentType – тип type создаваемого Blob-объекта, по умолчанию такой же, как и исходный.
Аргументы – как в array.slice , отрицательные числа также разрешены.
Мы не можем изменять данные напрямую в Blob, но мы можем делать срезы и создавать новый Blob на их основе, объединять несколько объектов в новый и так далее.
Это поведение аналогично JavaScript-строке: мы не можем изменить символы в строке, но мы можем создать новую исправленную строку на базе имеющейся.
Blob как URL
Давайте начнём с простого примера. При клике на ссылку мы загружаем динамически генерируемый Blob с hello world содержимым как файл:
); link.href = URL.createObjectURL(blob);
Мы также можем создать ссылку динамически, используя только JavaScript, и эмулировать на ней клик, используя link.click() , тогда загрузка начнётся автоматически.
Далее простой пример создания «на лету» и загрузки Blob-объекта, без использования HTML:
let link = document.createElement('a'); link.download = 'hello.txt'; let blob = new Blob(['Hello, world!'], ); link.href = URL.createObjectURL(blob); link.click(); URL.revokeObjectURL(link.href);
URL.createObjectURL берёт Blob и создаёт уникальный URL для него в формате blob:/ .
Вот как выглядит сгенерированный URL:
blob:https://javascript.info/1e67e00e-860d-40a5-89ae-6ab0cbee6273
Браузер для каждого URL, сгенерированного через URL.createObjectURL , сохраняет внутреннее соответствие URL → Blob . Таким образом, такие URL короткие, но дают доступ к большому объекту Blob .
Сгенерированный url действителен, только пока текущий документ открыт. Это позволяет ссылаться на сгенерированный в нём Blob в , или в любом другом объекте, где ожидается url в качестве одного из параметров.
В данном случае возможен побочный эффект. Пока в карте соответствия существует ссылка на Blob, он находится в памяти. Браузер не может освободить память, занятую Blob-объектом.
Ссылка в карте соответствия автоматически удаляется при выгрузке документа, после этого также освобождается память. Но если приложение имеет длительный жизненный цикл, это может произойти не скоро. Таким образом, если мы создадим URL для Blob, он будет висеть в памяти, даже если в нём нет больше необходимости.
URL.revokeObjectURL(url) удаляет внутреннюю ссылку на объект, что позволяет удалить его (если нет другой ссылки) сборщику мусора, и память будет освобождена.
В последнем примере мы использовали Blob только единожды, для мгновенной загрузки, после мы сразу же вызвали URL.revokeObjectURL(link.href) .
В предыдущем примере с кликабельной HTML-ссылкой мы не вызывали URL.revokeObjectURL(link.href) , потому что это сделало бы ссылку недействительной. После удаления внутренней ссылки на Blob , URL больше не будет работать.
Blob to base64
Альтернатива URL.createObjectURL – конвертация Blob-объекта в строку с кодировкой base64.
Эта кодировка представляет двоичные данные в виде строки с безопасными для чтения символами в ASCII-кодах от 0 до 64. И что более важно – мы можем использовать эту кодировку для «data-urls».
data url имеет форму data:[][;base64], . Мы можем использовать такой url где угодно наряду с «обычным» url.
Браузер декодирует строку и показывает смайлик:
Для трансформации Blob в base64 мы будем использовать встроенный в браузер объект типа FileReader . Он может читать данные из Blob в множестве форматов. В следующей главе мы рассмотрим это более глубоко.
Вот пример загрузки Blob при помощи base64:
let link = document.createElement('a'); link.download = 'hello.txt'; let blob = new Blob(['Hello, world!'], ); let reader = new FileReader(); reader.readAsDataURL(blob); // конвертирует Blob в base64 и вызывает onload reader.onload = function() < link.href = reader.result; // url с данными link.click(); >;
Оба варианта могут быть использованы для создания URL с Blob. Но обычно URL.createObjectURL(blob) является более быстрым и безопасным.
- Нужно отзывать объект для освобождения памяти.
- Прямой доступ к Blob, без «кодирования/декодирования».
- Нет необходимости что-либо отзывать.
- Потеря производительности и памяти при декодировании больших Blob-объектов.
Изображение в Blob
Мы можем создать Blob для изображения, части изображения или даже создать скриншот страницы. Что удобно для последующей загрузки куда-либо.
Операции с изображениями выполняются через элемент :
- Для отрисовки изображения (или его части) на холсте (canvas) используется canvas.drawImage.
- Вызов canvas-метода .toBlob(callback, format, quality) создаёт Blob и вызывает функцию callback при завершении.
В примере ниже изображение просто копируется, но мы можем взять его часть или трансформировать его на canvas перед созданием Blob:
// берём любое изображение let img = document.querySelector('img'); // создаём того же размера let canvas = document.createElement('canvas'); canvas.width = img.clientWidth; canvas.height = img.clientHeight; let context = canvas.getContext('2d'); // копируем изображение в canvas (метод позволяет вырезать часть изображения) context.drawImage(img, 0, 0); // мы можем вращать изображение при помощи context.rotate() и делать множество других преобразований // toBlob является асинхронной операцией, для которой callback-функция вызывается при завершении canvas.toBlob(function(blob) < // после того, как Blob создан, загружаем его let link = document.createElement('a'); link.download = 'example.png'; link.href = URL.createObjectURL(blob); link.click(); // удаляем внутреннюю ссылку на Blob, что позволит браузеру очистить память URL.revokeObjectURL(link.href); >, 'image/png');
Или если вы предпочитаете async/await вместо колбэка:
let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png'));
Для создания скриншота страницы мы можем использовать такую библиотеку, как https://github.com/niklasvh/html2canvas. Всё, что она делает, это просто проходит страницу и отрисовывает её в . После этого мы может получить Blob одним из вышеуказанных способов.
Из Blob в ArrayBuffer
Конструктор Blob позволяет создать Blob-объект практически из чего угодно, включая BufferSource .
Но если нам нужна производительная низкоуровневая обработка, мы можем использовать ArrayBuffer из FileReader :
// получаем arrayBuffer из Blob let fileReader = new FileReader(); fileReader.readAsArrayBuffer(blob); fileReader.onload = function(event) < let arrayBuffer = fileReader.result; >;
Итого
В то время как ArrayBuffer , Uint8Array и другие BufferSource являются «бинарными данными», Blob представляет собой «бинарные данные с типом».
Это делает Blob удобным для операций загрузки/выгрузки данных, которые так часто используются в браузере.
Методы, которые выполняют сетевые запросы, такие как XMLHttpRequest, fetch и подобные, могут изначально работать с Blob так же, как и с другими объектами, представляющими двоичные данные.
Мы можем легко конвертировать Blob в низкоуровневые бинарные типы данных и обратно:
- Мы можем создать Blob из типизированного массива, используя конструктор new Blob(. ) .
- Мы можем обратно создать ArrayBuffer из Blob, используя FileReader , а затем создать его представление для низкоуровневых операций.