Javascript blob to arraybuffer

JavaScript
Двоичные данные

Типизированные массивы были первоначально указаны в проекте редактора Khronos , а затем стандартизованы в ECMAScript 6 §24 и §22.2 .

Преобразование между Blobs и ArrayBuffers

JavaScript имеет два основных способа представления двоичных данных в браузере. ArrayBuffers / TypedArrays содержат изменчивые (хотя и фиксированные) двоичные данные, с которыми вы можете напрямую манипулировать. Blobs содержат неизменяемые двоичные данные, доступ к которым возможен только через асинхронный интерфейс File.

Преобразование Blob в ArrayBuffer (асинхронный)

var blob = new Blob(["\x01\x02\x03\x04"]), fileReader = new FileReader(), array; fileReader.onload = function() < array = this.result; console.log("Array contains", array.byteLength, "bytes."); >; fileReader.readAsArrayBuffer(blob); 

Преобразование Blob в ArrayBuffer с использованием Promise (асинхронный)

var blob = new Blob(["\x01\x02\x03\x04"]); var arrayPromise = new Promise(function(resolve) < var reader = new FileReader(); reader.onloadend = function() < resolve(reader.result); >; reader.readAsArrayBuffer(blob); >); arrayPromise.then(function(array) < console.log("Array contains", array.byteLength, "bytes."); >); 

Преобразование ArrayBuffer или типизированного массива в Blob

var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]); var blob = new Blob([array]); 

Манипулирование массивами с помощью DataViews

DataViews предоставляют методы для чтения и записи отдельных значений из ArrayBuffer, а не для просмотра всего объекта как массива одного типа. Здесь мы устанавливаем два байта отдельно, а затем интерпретируем их вместе как 16-разрядное целое без знака, первое из которых является big-endian then little-endian.

var buffer = new ArrayBuffer(2); var view = new DataView(buffer); view.setUint8(0, 0xFF); view.setUint8(1, 0x01); console.log(view.getUint16(0, false)); // 65281 console.log(view.getUint16(0, true)); // 511 

Создание TypedArray из строки Base64

var data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACN' + 'byblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHx' + 'gljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='; var characters = atob(data); var array = new Uint8Array(characters.length); for (var i = 0; i

Использование TypedArrays

TypedArrays — это набор типов, предоставляющих различные виды в изменяемые бинарные массивы ArrayBuffers с фиксированной длиной. По большей части они действуют как массивы, которые принуждают все назначенные значения к заданному числовому типу. Вы можете передать экземпляр ArrayBuffer в конструктор TypedArray для создания нового представления его данных.

var buffer = new ArrayBuffer(8); var byteView = new Uint8Array(buffer); var floatView = new Float64Array(buffer); console.log(byteView); // [0, 0, 0, 0, 0, 0, 0, 0] console.log(floatView); // [0] byteView[0] = 0x01; byteView[1] = 0x02; byteView[2] = 0x04; byteView[3] = 0x08; console.log(floatView); // [6.64421383e-316] 

ArrayBuffers можно скопировать с использованием .slice(. ) , либо напрямую, либо через представление TypedArray.

var byteView2 = byteView.slice(); var floatView2 = new Float64Array(byteView2.buffer); byteView2[6] = 0xFF; console.log(floatView); // [6.64421383e-316] console.log(floatView2); // [7.06327456e-304] 

Получение двоичного представления файла изображения

// preliminary code to handle getting local file and finally printing to console // the results of our function ArrayBufferToBinary(). var file = // get handle to local file. var reader = new FileReader(); reader.onload = function(event) < var data = event.target.result; console.log(ArrayBufferToBinary(data)); >; reader.readAsArrayBuffer(file); //gets an ArrayBuffer of the file 

Теперь мы выполняем фактическое преобразование данных файла в 1 и 0 с помощью DataView :

function ArrayBufferToBinary(buffer) < // Convert an array buffer to a string bit-representation: 0 1 1 0 0 0. var dataView = new DataView(buffer); var response = "", offset = (8/8); for(var i = 0; i < dataView.byteLength; i += offset) < response += dataView.getInt8(i).toString(2); >return response; > 

DataView позволяет читать / записывать числовые данные; getInt8 преобразует данные из позиции байта — здесь 0 , значение, переданное в — в ArrayBuffer к подписанному 8-битовому целочисленному представлению, а toString(2) преобразует 8-разрядное целое в формат двоичного представления (то есть строку из 1 и 0 ‘).

Читайте также:  Php format datetime atom

Файлы сохраняются как байты. Значение «магического» смещения получается, если мы принимаем файлы, хранящиеся в байтах, т. Е. Как 8-битные целые числа и считываем их в 8-битном целочисленном представлении. Если бы мы пытались прочитать наши байтовые (т. Е. 8-битные) файлы в 32-битные целые числа, отметим, что 32/8 = 4 — это количество байтовых пробелов, которое является нашим значением смещения байта.

Для этой задачи DataView s излишне. Они обычно используются в случаях, когда встречаются сущность или неоднородность данных (например, при чтении PDF-файлов, которые имеют заголовки, закодированные в разных базах, и мы хотели бы осмысленно извлечь это значение). Поскольку нам просто нужно текстовое представление, мы не заботимся о гетерогенности, поскольку никогда не нужно

Решение гораздо лучше — и короче — можно найти с помощью массива, типизированного в UInt8Array , который обрабатывает весь ArrayBuffer как состоящий из 8-битных целых чисел без знака:

function ArrayBufferToBinary(buffer) < var uint8 = new Uint8Array(buffer); return uint8.reduce((binary, uint8) =>binary + uint8.toString(2), ""); > 

Итерация через массивBuffer

Для удобного способа итерации через arrayBuffer вы можете создать простой итератор, который реализует методы DataView под капотом:

var ArrayBufferCursor = function() < var ArrayBufferCursor = function(arrayBuffer) < this.dataview = new DataView(arrayBuffer, 0); this.size = arrayBuffer.byteLength; this.index = 0; >ArrayBufferCursor.prototype.next = function(type) < switch(type) < case 'Uint8': var result = this.dataview.getUint8(this.index); this.index += 1; return result; case 'Int16': var result = this.dataview.getInt16(this.index, true); this.index += 2; return result; case 'Uint16': var result = this.dataview.getUint16(this.index, true); this.index += 2; return result; case 'Int32': var result = this.dataview.getInt32(this.index, true); this.index += 4; return result; case 'Uint32': var result = this.dataview.getUint32(this.index, true); this.index += 4; return result; case 'Float': case 'Float32': var result = this.dataview.getFloat32(this.index, true); this.index += 4; return result; case 'Double': case 'Float64': var result = this.dataview.getFloat64(this.index, true); this.index += 8; return result; default: throw new Error("Unknown datatype"); >>; ArrayBufferCursor.prototype.hasNext = function() < return this.index < this.size; >return ArrayBufferCursor; >); 

Затем вы можете создать итератор следующим образом:

var cursor = new ArrayBufferCursor(arrayBuffer); 

Вы можете использовать hasNext чтобы проверить, есть ли еще элементы

Вы можете использовать next метод для следующего значения:

var nextValue = cursor.next('Float'); 

С таким итератором писать собственный парсер для обработки двоичных данных становится довольно легко.

  • Начало работы с JavaScript
  • .postMessage () и MessageEvent
  • AJAX
  • API веб-криптографии
  • API вибрации
  • API выбора
  • API состояния батареи
  • API уведомлений
  • Callbacks
  • execCommand и contenteditable
  • IndexedDB
  • JSON
  • Linters — Обеспечение качества кода
  • Loops
  • requestAnimationFrame
  • Timestamps
  • Transpiling
  • WeakMap
  • WeakSet
  • WebSockets
  • Автоматическая точка с запятой — ASI
  • Анти-паттерны
  • Арифметика (математика)
  • Асинхронные итераторы
  • Асинхронные функции (async / await)
  • Атрибуты данных
  • Веб-хранилище
  • Встроенные константы
  • Генераторы
  • геолокации
  • Глобальная обработка ошибок в браузерах
  • Дата
  • Двоичные данные
  • Единичное тестирование Javascript
  • Задавать
  • Зарезервированные ключевые слова
  • Интервалы и тайм-ауты
  • Использование javascript для получения / установки пользовательских переменных CSS
  • история
  • Как заставить итератор использоваться внутри функции асинхронного обратного вызова
  • карта
  • Классы
  • Комментарии
  • Контекст (это)
  • Литералы шаблонов
  • локализация
  • Манипуляция данными
  • Массивы
  • Методы модуляции
  • Модалы — подсказки
  • Модули
  • Назначение деструктуризации
  • наследование
  • обещания
  • Обнаружение браузера
  • Обработка ошибок
  • Объект Navigator
  • Объекты
  • Объем
  • Объявления и задания
  • Операции сравнения
  • Оптимизация звонков
  • отладка
  • Оценка JavaScript
  • Переменное принуждение / преобразование
  • Переменные JavaScript
  • Перечисления
  • Печенье
  • Побитовые операторы
  • Побитовые операторы — примеры реального мира (фрагменты)
  • Поведенческие шаблоны проектирования
  • полномочие
  • получать
  • Пользовательские элементы
  • Последовательности выхода
  • Приставка
  • Проблемы с безопасностью
  • Пространства имен
  • Прототипы, объекты
  • Рабочие
  • Регулярные выражения
  • Свободный API
  • Сети и Getters
  • Символы
  • События
  • События, отправленные сервером
  • Советы по повышению производительности
  • Создание шаблонов проектирования
  • Спецификация (модель объекта браузера)
  • Сравнение даты
  • Строгий режим
  • Струны
  • Та же политика происхождения и перекрестная связь
  • Тильда ~
  • Типы данных в Javascript
  • Унарные операторы
  • условия
  • Файловый API, Blobs и FileReaders
  • функции
  • Функции конструктора
  • Функции стрелки
  • Функциональный JavaScript
  • Цепочка метода
  • Цикл событий
  • экран
  • Эффективность памяти

Источник

How to go from Blob to ArrayBuffer

You can use FileReader to read the Blob as an ArrayBuffer .

var arrayBuffer; var fileReader = new FileReader(); fileReader.onload = function(event) < arrayBuffer = event.target.result; >; fileReader.readAsArrayBuffer(blob); 
// ArrayBuffer -> Blob var uint8Array = new Uint8Array([1, 2, 3]); var arrayBuffer = uint8Array.buffer; var blob = new Blob([arrayBuffer]); // Blob -> ArrayBuffer var uint8ArrayNew = null; var arrayBufferNew = null; var fileReader = new FileReader(); fileReader.onload = function(event) < arrayBufferNew = event.target.result; uint8ArrayNew = new Uint8Array(arrayBufferNew); // warn if read values are not the same as the original values // arrayEqual from: http://stackoverflow.com/questions/3115982/how-to-check-javascript-array-equals function arrayEqual(a, b) < return !(a; if (arrayBufferNew.byteLength !== arrayBuffer.byteLength) // should be 3 console.warn("ArrayBuffer byteLength does not match"); if (arrayEqual(uint8ArrayNew, uint8Array) !== true) // should be [1,2,3] console.warn("Uint8Array does not match"); >; fileReader.readAsArrayBuffer(blob); fileReader.result; // also accessible this way once the blob has been read 

This was tested out in the console of Chrome 27—69, Firefox 20—60, and Safari 6—11.

Here’s also a live demonstration which you can play with: https://jsfiddle.net/potatosalad/FbaM6/

Update 2018-06-23: Thanks to Klaus Klein for the tip about event.target.result versus this.result

  • https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsArrayBuffer()
  • https://www.w3.org/TR/FileAPI/#dfn-readAsArrayBuffer

Or you can use the fetch API

fetch(URL.createObjectURL(myBlob)).then(res => res.arrayBuffer()) 

I don’t know what the performance difference is, and this will show up on your network tab in DevTools as well.

Just to complement Mr @potatosalad answer.

You don’t actually need to access the function scope to get the result on the onload callback, you can freely do the following on the event parameter:

var arrayBuffer; var fileReader = new FileReader(); fileReader.onload = function(event) < arrayBuffer = event.target.result; >; fileReader.readAsArrayBuffer(blob); 

Why this is better? Because then we may use arrow function without losing the context

var fileReader = new FileReader(); fileReader.onload = (event) => < this.externalScopeVariable = event.target.result; >; fileReader.readAsArrayBuffer(blob); 

The Response API consumes a (immutable) Blob from which the data can be retrieved in several ways. The OP only asked for ArrayBuffer , and here’s a demonstration of it.

var blob = GetABlobSomehow(); // NOTE: you will need to wrap this up in a async block first. /* Use the await keyword to wait for the Promise to resolve */ await new Response(blob).arrayBuffer(); //=>

alternatively you could use this:

new Response(blob).arrayBuffer() .then(/* */); 

Note: This API isn’t compatible with older (ancient) browsers so take a look to the Browser Compatibility Table to be on the safe side 😉

Источник

Оцените статью