Як дістатися з Blob до ArrayBuffer


111

Я вивчав Blobs, і я помітив, що коли у вас є ArrayBuffer, ви можете легко перетворити це на Blob так:

var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });

Зараз у мене питання, чи можна переходити з Blob до ArrayBuffer?


2
Краплі не в рідному форматі JS. Вони схожі на посилання на дані, але не на фактичні дані. Дані з Blobне можна безпосередньо прочитати, але це можна зробити за допомогою деяких API.
tripulse

Відповіді:


39

ResponseAPI споживає (незмінне) , Blobз якого дані можуть бути отримані декількома способами. OP тільки просив ArrayBuffer, а ось демонстрація цього.

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();   //=> <ArrayBuffer>

Ви також можете скористатися цим:

new Response(blob).arrayBuffer()
.then(/* <function> */);

Примітка. Цей API не сумісний зі старими ( старовинними ) браузерами, тому перегляньте таблицю сумісності браузера, щоб бути на безпечній стороні;)


1
Це має бути головна відповідь ІМО.
Кемерон Мартін

const arrayBuffer = чекаємо нового відповіді (blob) .arrayBuffer ();
Р.Ча

1
@ R.Cha Дякую за виправлення. Я цього не помічав!
tripulse

2
Розумна хитрість і не плутати з Blob.arrayBuffer()якою насправді має досить погану сумісність навіть у 2020 році, caniuse.com/#feat=mdn-api_blob_arraybuffer або developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
jpschroeder

Яка ефективність цього? Чи він копіює дані на Blob або просто повертає їх уявлення?
GaryO

141

Ви можете використовувати FileReaderдля читання Blobяк 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<b || b<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

Це було перевірено на консолях Chrome 27—69, Firefox 20—60 та Safari 6—11.

Ось також демонстрація в прямому ефірі, з якою можна грати: https://jsfiddle.net/potatosalad/FbaM6/

Оновлення 2018-06-23: Дякую Клаусу Кляйна за підказку щодо event.target.resultпорівняноthis.result

Довідка:


23
це не здається великим кодом .. для чогось, що має бути простим?
Henley Chiu

3
@HenleyChiu Я відредагував відповідь, щоб включити коротку версію коду. Більш довгий приклад повинен бути повністю автономним (показує, як створити ArrayBuffer, Blob і назад знову). Мені не вдалося знайти синхронний спосіб зчитувати Blob без використання Web Worker і FileReaderSync .
картопляний салат

1
Деякі люди справді хочуть довести, що пекло зворотного дзвінка існує. Це має сенс для ВЕЛИКІ краплі, але для випадків звичайного використання JavaScript повинен забезпечувати метод синхронізації.
lama12345

це було дуже корисно
Джиммі Обеніо Абор

@Anuj Ви зробили неправильно. Це не повинно посилатися this. <EventTarget>.resultповинні це виправити!
tripulse

17

Просто для доповнення відповіді містера @potatosalad.

Ви на самому справі не потрібно , щоб отримати доступ до функції сфери , щоб отримати результат на OnLoad зворотного виклику, ви можете вільно зробити наступне на подію параметра:

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

Чому це краще? Тому що тоді ми можемо використовувати функцію стрілки, не втрачаючи контексту

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

15

Або ви можете скористатися API для отримання

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

Я не знаю, в чому різниця в продуктивності, і це з’явиться на вкладці мережі в DevTools також.


17
Або простоnew Response(blob).arrayBuffer()
Нескінченні

4

Існує в даний час (& FF 69+ хром 76+) а Blob.prototype.arrayBuffer () метод , який буде повертати Promise рішення з ArrayBuffer , що представляє дані згустку в.

(async () => {
  const blob = new Blob(['hello']);
  const buf = await blob.arrayBuffer();
  console.log( buf.byteLength ); // 5
})();


2
На жаль, наразі не працює в Safari (поки)
HerrZatacke
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.