Cara beralih dari Blob ke ArrayBuffer

111

Saya sedang mempelajari Blob, dan saya perhatikan bahwa ketika Anda memiliki ArrayBuffer, Anda dapat dengan mudah mengonversinya menjadi Blob sebagai berikut:

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

Pertanyaan yang saya miliki sekarang adalah, apakah mungkin untuk beralih dari Blob ke ArrayBuffer?

Jeanluca Scaljeri
sumber
2
Blob tidak dalam format JS asli. Mereka seperti referensi ke data tetapi bukan data sebenarnya. Data dari a Blobtidak dapat langsung dibaca tetapi dapat dilakukan dengan beberapa API.
tripulse

Jawaban:

39

The ResponseAPI mengkonsumsi (berubah) Blobdari mana data dapat diambil dalam beberapa cara. Para OP hanya meminta ArrayBuffer, dan inilah demonstrasi itu.

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>

alternatifnya Anda bisa menggunakan ini:

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

Catatan: Ini API tidak kompatibel dengan yang lebih tua ( kuno browser) sehingga kita lihat ke Browser Compatibility Table untuk berada di sisi yang aman;)

tripulse
sumber
1
Ini harus menjadi jawaban IMO teratas.
Cameron Martin
const arrayBuffer = menunggu Respon baru (blob) .arrayBuffer ();
R.Cha
1
@ R.Cha Terima kasih atas perbaikannya. Saya tidak menyadarinya!
tripulse
2
Trik cerdas dan tidak perlu bingung dengan Blob.arrayBuffer()mana yang sebenarnya memiliki kompatibilitas yang cukup buruk bahkan di tahun 2020, caniuse.com/#feat=mdn-api_blob_arraybuffer atau developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
jpschroeder
Apa kinerja ini? Apakah itu menyalin data di Blob atau hanya menampilkannya saja?
GaryO
141

Anda dapat menggunakan FileReaderuntuk membaca Blobsebagai file ArrayBuffer.

Berikut contoh singkatnya:

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

Berikut contoh yang lebih panjang:

// 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

Ini telah diuji di konsol Chrome 27—69, Firefox 20—60, dan Safari 6—11.

Berikut juga demonstrasi langsung yang dapat Anda mainkan: https://jsfiddle.net/potatosalad/FbaM6/

Perbarui 2018-06-23: Terima kasih kepada Klaus Klein untuk tip tentang event.target.resultversusthis.result

Referensi:

salad kentang
sumber
23
bukankah ini tampak seperti banyak kode .. untuk sesuatu yang seharusnya sederhana?
Henley Chiu
3
@HenleyChiu Saya mengedit jawaban untuk menyertakan versi singkat kode. Contoh yang lebih panjang dimaksudkan untuk menjadi mandiri sepenuhnya (menunjukkan cara membuat ArrayBuffer, Blob, dan kembali lagi). Saya belum dapat menemukan cara sinkron untuk membaca Blob tanpa menggunakan Web Worker dan FileReaderSync .
potatosalad
1
Beberapa orang benar-benar ingin membuktikan neraka panggilan balik itu ada. Masuk akal untuk blob BESAR, tetapi untuk kasus penggunaan normal JavaScript harus menyediakan metode sinkronisasi.
lama12345
ini sangat berguna
Jimmy Obonyo Abor
@Anuj Anda telah melakukan kesalahan. Seharusnya tidak mengacu pada this. <EventTarget>.resultharus memperbaikinya!
tripulse
17

Sekadar melengkapi jawaban Pak @potatosalad.

Anda sebenarnya tidak perlu mengakses cakupan fungsi untuk mendapatkan hasil pada callback onload , Anda dapat dengan bebas melakukan hal berikut pada parameter peristiwa :

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

Mengapa ini lebih baik? Karena dengan demikian kita dapat menggunakan fungsi panah tanpa kehilangan konteksnya

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

Atau Anda dapat menggunakan API pengambilan

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

Saya tidak tahu apa perbedaan kinerjanya, dan ini akan muncul di tab jaringan Anda di DevTools juga.

Arlen Beiler
sumber
17
Atau hanyanew Response(blob).arrayBuffer()
Endless
4

Ada sekarang (76+ & FF 69+ Chrome) a Blob.prototype.arrayBuffer () metode yang akan mengembalikan Janji menyelesaikan dengan ArrayBuffer mewakili data Blob ini.

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

Kaiido
sumber
2
Sayangnya saat ini tidak bekerja di Safari (belum)
HerrZatacke