Cách đi từ Blob đến ArrayBuffer


110

Tôi đang nghiên cứu Blob và tôi nhận thấy rằng khi bạn có ArrayBuffer, bạn có thể dễ dàng chuyển đổi nó thành Blob như sau:

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

Câu hỏi tôi đặt ra bây giờ là, liệu có thể chuyển từ Blob sang ArrayBuffer không?


2
Các đốm màu không ở định dạng JS gốc. Chúng giống như các tham chiếu đến dữ liệu nhưng không phải là dữ liệu thực tế. Dữ liệu từ a Blobkhông thể được đọc trực tiếp nhưng nó có thể được thực hiện với một số API.
tripulse

Câu trả lời:


39

Các ResponseAPI tiêu thụ một (không thay đổi) Blobmà từ đó các dữ liệu có thể được lấy ra bằng nhiều cách. Các OP chỉ yêu cầu ArrayBuffer, và đây là một cuộc biểu tình của nó.

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>

hoặc bạn có thể sử dụng cái này:

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

Lưu ý: Đây API không tương thích với cũ ( cổ các trình duyệt) để có một cái nhìn vào tương thích trình duyệt Bảng để được ở bên an toàn;)


1
Đây phải là câu trả lời hàng đầu IMO.
Cameron Martin

const arrayBuffer = chờ Phản hồi mới (blob) .arrayBuffer ();
R.Cha

1
@ R.Cha Cảm ơn bạn đã sửa lỗi. Tôi không nhận thấy điều đó!
chuyến đi

2
Bí quyết thông minh và không nên nhầm lẫn với Blob.arrayBuffer()thứ thực sự có khả năng tương thích khá kém ngay cả trong năm 2020, caniuse.com/#feat=mdn-api_blob_arraybuffer hoặc developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer
jpschroeder

Hiệu suất của cái này là gì? Nó có sao chép dữ liệu trong Blob hay chỉ trả lại một chế độ xem của nó?
GaryO

141

Bạn có thể sử dụng FileReaderđể đọc Blobnhư một ArrayBuffer.

Đây là một ví dụ ngắn gọn:

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

Đây là một ví dụ dài hơn:

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

Điều này đã được thử nghiệm trong bảng điều khiển của Chrome 27—69, Firefox 20—60 và Safari 6—11.

Đây cũng là phần trình diễn trực tiếp mà bạn có thể chơi: https://jsfiddle.net/potatosalad/FbaM6/

Cập nhật 2018-06-23: Cảm ơn Klaus Klein về mẹo về event.target.resultso vớithis.result

Tài liệu tham khảo:


22
Điều này có vẻ giống như rất nhiều mã .. cho một cái gì đó phải đơn giản?
Henley Chiu

2
@HenleyChiu Tôi đã chỉnh sửa câu trả lời để bao gồm một phiên bản ngắn của mã. Ví dụ dài hơn nhằm mục đích hoàn toàn độc lập (chỉ ra cách tạo Bộ đệm ArrayBuffer, Blob và quay lại lần nữa). Tôi không thể tìm thấy một cách đồng bộ để đọc Blob mà không sử dụng Web WorkerFileReaderSync .
potatosalad

1
Một số người thực sự muốn chứng minh địa ngục gọi lại tồn tại. Nó có ý nghĩa đối với các đốm màu LARGE, nhưng đối với các trường hợp sử dụng thông thường, JavaScript nên cung cấp một phương pháp đồng bộ hóa.
lama12345

điều này rất hữu ích
Jimmy Obonyo Abor

@Anuj Bạn đã làm sai. Nó không nên đề cập đến this. <EventTarget>.resultnên khắc phục điều đó!
tripulse

17

Chỉ để bổ sung cho câu trả lời của Mr @potatosalad.

Bạn thực sự không cần phải truy cập phạm vi chức năng để nhận kết quả trên lệnh gọi lại onload , bạn có thể tự do thực hiện như sau trên tham số sự kiện :

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

Tại sao điều này tốt hơn? Vì khi đó chúng ta có thể sử dụng hàm mũi tên mà không làm mất ngữ cảnh

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

15

Hoặc bạn có thể sử dụng API tìm nạp

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

Tôi không biết sự khác biệt về hiệu suất là gì và điều này cũng sẽ hiển thị trên tab mạng của bạn trong DevTools.


17
Hoặc chỉnew Response(blob).arrayBuffer()
Endless

4

tại (& FF 69+ Chrome 76+) một Blob.prototype.arrayBuffer () phương pháp mà sẽ trả về một Promise giải quyết với một ArrayBuffer đại diện cho dữ liệu của Blob.

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


2
Rất tiếc, hiện không hoạt động trong Safari (chưa)
HerrZatacke
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.