atob
Функция будет декодировать в кодировке Base64 строку в новую строку с символом для каждого байта двоичных данных.
const byteCharacters = atob(b64Data);
Кодовая точка каждого символа (charCode) будет значением байта. Мы можем создать массив байтовых значений, применяя это, используя .charCodeAt
метод для каждого символа в строке.
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Вы можете преобразовать этот массив байтовых значений в реальный типизированный байтовый массив, передав его Uint8Array
конструктору.
const byteArray = new Uint8Array(byteNumbers);
Это, в свою очередь, может быть преобразовано в BLOB, обернув его в массив и передав его Blob
конструктору.
const blob = new Blob([byteArray], {type: contentType});
Код выше работает. Однако производительность можно немного улучшить, обработав byteCharacters
меньшие кусочки, а не все сразу. В моем грубом тестировании 512 байт, кажется, хороший размер среза. Это дает нам следующую функцию.
const b64toBlob = (b64Data, contentType='', 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;
}
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Полный пример:
const b64toBlob = (b64Data, contentType='', 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;
}
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
Вот более минимальный метод без каких-либо зависимостей или библиотек.
Требуется новый API выборки. ( Могу ли я использовать это? )
С помощью этого метода вы также можете легко получить ReadableStream, ArrayBuffer, text и JSON.
Как функция:
Я сделал простой тест производительности для версии синхронизации Jeremy ES6.
Синхронизированная версия на некоторое время заблокирует пользовательский интерфейс. держать devtool открытым может снизить производительность выборки
Показать фрагмент кода
источник
createObjectURL
аreadAsDataURL
не намного лучше например. И если вы загружаете файлы, используя ajax, выберитеFormData
вместоJSON
или используйтеcanvas.toBlob
вместоtoDataURL
await (await fetch(imageDataURL)).blob()
await fetch(url).then(r=>r.blob())
сортируетсяAccess is denied.
ошибки. Я полагаю, чтоfetch
BLOB-URL.createObjectUrl
объект выставляется под URL-адресом BLOB-объекта - таким же образом , что и не будет работать на ie11. ссылка . Может быть, есть какой-нибудь способ использовать fetch с IE11? Это выглядит намного лучше, чем другие решения для синхронизации :)Оптимизированная (но менее читаемая) реализация:
источник
Для поддержки всех браузеров, особенно на Android, возможно, вы можете добавить это:
источник
Для данных изображений я считаю, что проще использовать
canvas.toBlob
(асинхронный)источник
image/jpg
из строки base64, а затем передавая его в качестве второго параметра вtoBlob
функцию, чтобы результат был того же типа. Кроме того, я думаю, что это идеально - это экономит 30% трафика и вашего дискового пространства на сервере (по сравнению с base64), и работает хорошо даже с прозрачным PNG.Смотрите этот пример: https://jsfiddle.net/pqhdce2L/
источник
Я заметил, что Internet Explorer 11 работает невероятно медленно при разрезании данных, как предложил Джереми. Это верно для Chrome, но Internet Explorer, похоже, испытывает проблемы при передаче нарезанных данных в Blob-конструктор. На моей машине пропуск 5 МБ данных приводит к сбою Internet Explorer, а потребление памяти становится все выше. Chrome создает блоб в кратчайшие сроки.
Запустите этот код для сравнения:
Поэтому я решил включить оба метода, описанных Джереми, в одну функцию. Кредиты идут к нему за это.
источник
Для всех любителей копирования и вставки, таких как я, есть готовая функция загрузки, которая работает в Chrome, Firefox и Edge:
источник
createObjectURL
не принимает 2 - й аргумента ...Если вы можете выдержать добавление одной зависимости к вашему проекту, есть отличный
blob-util
пакет npm, который предоставляет удобнуюbase64StringToBlob
функцию. После добавленияpackage.json
вы можете использовать его следующим образом:источник
Я публикую более декларативный способ синхронизации Base64 преобразования. Хотя async
fetch().blob()
очень аккуратный, и мне очень нравится это решение, оно не работает в Internet Explorer 11 (и, возможно, Edge - я его не тестировал), даже с polyfill - взгляните на мой комментарий к Endless ' пост для более подробной информации.бонус
Если вы хотите распечатать его, вы можете сделать что-то вроде:
Бонус x 2 - Открытие BLOB-файла в новой вкладке для Internet Explorer 11
Если вы можете выполнить некоторую предварительную обработку строки Base64 на сервере, вы можете открыть ее по некоторому URL и использовать ссылку в
printJS
:)источник
Ниже приведен мой код TypeScript, который можно легко преобразовать в JavaScript, и вы можете использовать
источник
Typescript code
код имеет только один тип, и этот типany
. Как то зачем вообще беспокоиться ??Метод с fetch - лучшее решение, но если кому-то нужно использовать метод без fetch, то вот оно, как упоминалось ранее, у меня не сработало:
источник