2

I am writing an Angular/TypeScript app in Cordova that needs to download a binary file from a server.

Based upon another question, I could find out that I need to set an appropriate response type on the request parameters to prevent Angular from attempting to interpret the response body as JSON (which would lead to a crash, as it's binary data).

Answers in that question and the docs point me to Blob and ArrayBuffer as likely values.

Unfortunately, I cannot find any explanation on what is the difference between these two (no, the respective question has not really enlightened me), and both fail in their own ways.

ArrayBuffer

When using this, my app crashes with a RangeError due to exceeding some maximum stack size deep down in the internals of Angular1.

Blob

With this, the request goes through, but unless I'm missing something, the debugger shows that I am only getting a small object withe blob size and the MIME type, but the actual binary data is missing!

What's more, the answer on the aforementioned question points out a TextDecoder to "decode the result".

Can't I just get the binary response body as a byte array somehow?


1: That I actually have to extend this app that was started by another (more or less inaccessible to me) team, whose members added several layers of wrapping and parameter/result transformation around Angular's Http service does not make things easier to debug, but I am pretty confident I have set my breakpoints at the bottommost level and am thus not experiencing any effects of the wrappers.

O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114

1 Answers1

0

To access blob as byte array, use FileReader:

//use slice if your blob is too big
var chunkBlob = blobObject.slice(offset, chunk_size);

var fileReader = new FileReader();
fileReader.onload = function() {
    var byteArray = new Uint8Array(this.result);
}
fileReader.readAsArrayBuffer(chunkBlob);

As for the difference between Blob and ArrayBuffer, there isn't much you can do to a blob object. In contrast, ArrayBuffer can be accessed synchronously via DataView, TypedArray, or TextDecoder. ArrayBuffer is part of ECMAScript, but Blob is not.

From mozilla.org:

A Blob object represents a file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format.

cshu
  • 5,654
  • 28
  • 44
  • I don't quite understand. Where does `slice` in the first line come from? Are you saying the data is actually in the object, but hidden from the debugger, so I have to extract it by means of some `slice` method? – O. R. Mapper Nov 04 '17 at 08:56
  • @O.R.Mapper `slice` on blob works in a similar way as string. It just returns a smaller partial blob. Usually that first line should be unnecessary. I just worry about the size of blob might be too big. – cshu Nov 04 '17 at 09:04
  • Once I realized I had to capture the `onloadend` event, I could wrap this process into a promise that returns the `Uint8Array` in the end, so it works now. Thank you! – O. R. Mapper Nov 07 '17 at 15:31