Blob'dan ArrayBuffer'a nasıl gidilir


111

Bloblar üzerinde çalışıyordum ve bir ArrayBuffer'ınız olduğunda bunu bir Blob'a aşağıdaki gibi kolayca dönüştürebileceğinizi fark ettim:

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

Şimdi sorduğum soru, bir Blob'dan ArrayBuffer'a gitmek mümkün mü?


2
Bloblar yerel JS biçiminde değildir. Verilere referans gibidirler ancak gerçek verilere değil. A'dan gelen veriler Blobdoğrudan okunamaz, ancak bazı API'ler ile yapılabilir.
2019, 13

Yanıtlar:


39

ResponseAPI (iletmenin) tüketir Blobveriler çeşitli yöntemlerle alınabilir olan. OP sadece istedi ArrayBufferve burada bunun bir göstergesi.

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>

alternatif olarak bunu kullanabilirsiniz:

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

Not: Bu API , eski ( eski ) tarayıcılarla uyumlu değildir, bu nedenle güvenli tarafta olmak için Tarayıcı Uyumluluk Tablosu'na bir göz atın ;)


1
Bu en iyi cevap IMO olmalıdır.
Cameron Martin

const arrayBuffer = yeni Response (blob) .arrayBuffer ();
R.Cha

1
@ R.Cha Düzeltme için teşekkürler. Ben bunu fark etmedim!
19:39 tripulse

2
Blob.arrayBuffer()2020'de bile oldukça zayıf uyumluluğa sahip olan akıllıca bir numara ve karıştırılmaması gereken , caniuse.com/#feat=mdn-api_blob_arraybuffer veya developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
jpschroeder

Bunun performansı nedir? Verileri Blob'a mı kopyalıyor yoksa sadece bir görünümünü mi döndürüyor?
GaryO

141

Sen kullanabilirsiniz FileReaderokumak için Blobbir şekilde ArrayBuffer.

İşte kısa bir örnek:

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

İşte daha uzun bir örnek:

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

Bu, Chrome 27—69, Firefox 20—60 ve Safari 6—11 konsolunda test edilmiştir.

İşte oynayabileceğiniz canlı bir gösteri: https://jsfiddle.net/potatosalad/FbaM6/

2018-06-23 Güncellemesi:event.target.result Versus ile ilgili tüyo için Klaus Klein'a teşekkürlerthis.result

Referans:


24
bu çok fazla kod gibi görünmüyor mu .. basit olması gereken bir şey için?
Henley Chiu

3
@HenleyChiu Cevabı kodun kısa bir versiyonunu içerecek şekilde düzenledim. Daha uzun örnek, tamamen bağımsız olması amaçlanmıştır (ArrayBuffer, Blob ve tekrar nasıl oluşturulacağını gösterir). Bir Web Çalışanı ve FileReaderSync kullanmadan bir Blob'u okumanın eşzamanlı bir yolunu bulamadım .
patates salatası

1
Bazı insanlar geri arama cehenneminin var olduğunu gerçekten kanıtlamak ister. LARGE blob'lar için mantıklıdır, ancak normal kullanım durumları için JavaScript'in bir senkronizasyon yöntemi sağlaması gerekir.
lama12345

bu çok faydalı oldu
Jimmy Obonyo Abor

@Anuj Yanlış yaptın. İfade etmemeli this. <EventTarget>.resultbunu düzeltmeli!
2019

17

Sadece Bay @ patates salatası cevabını tamamlamak için.

Aslında onload geri aramasının sonucunu almak için işlev kapsamına erişmeniz gerekmez , olay parametresinde aşağıdakileri özgürce yapabilirsiniz :

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

Bu neden daha iyi? Çünkü o zaman içeriği kaybetmeden ok işlevini kullanabiliriz

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

15

Ya da getirme API'sini kullanabilirsiniz

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

Performans farkının ne olduğunu bilmiyorum ve bu, DevTools'taki ağ sekmenizde de görünecek.


17
Ya da sadecenew Response(blob).arrayBuffer()
Sonsuz

5

Orada hemen (Krom 76+ ve FF 69+) bir Blob.prototype.arrayBuffer () Promise Blob verilerini temsil eden bir ArrayBuffer ile çözme döner yöntemi.

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


2
Maalesef şu anda Safari'de çalışmıyor (henüz)
HerrZatacke
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.