Dev
Dev

Reputation: 1746

Converting array buffer to string - Maximum call stack size exceeded

Our app downloads a zip file, but the response is in binary.

So what I did is to convert it to base64. It works when the size is 87.7KB but an error occurs when the response size is 183KB.

The error is Uncaught RangeError: Maximum call stack size exceeded

The line in question is

btoa(String.fromCharCode.apply(null, new Uint8Array(blob)))

According to this answer, the String.fromCharCode.apply() must be replaced with TextEncoder.

So I changed it to

btoa(new TextDecoder('utf-8').decode(new Uint8Array(blob)))

but I get an error.

Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

I changed it again using the top most snippet of this answer

The new code is now

btoa(unescape(encodeURIComponent(new TextDecoder('utf-8').decode(new Uint8Array(blob)))))

The download now works but the download zip file is corrupted.

The whole code can be seen here

Upvotes: 19

Views: 12387

Answers (2)

Benito Gómez
Benito Gómez

Reputation: 35

https://stackoverflow.com/a/40077712/6582356

function blobToB64(data) {
    if ('TextDecoder' in window) {
      // Decode as UTF-8
      var dataView = new DataView(data);
      var decoder = new TextDecoder('utf8');
      return btoa(decoder.decode(dataView));
    } else {
      // Fallback
      return btoa(new Uint8Array(data).reduce((data, byte) =>
        data + String.fromCharCode(byte),
        ''))
    }
}

https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder

This one is seems to have better performance

Upvotes: -2

Dev
Dev

Reputation: 1746

I got my answer from another question

btoa(new Uint8Array(blob).reduce(function (data, byte) {
    return data + String.fromCharCode(byte);
}, ''));

Source

Upvotes: 47

Related Questions