Converting arraybuffer to string : Maximum call stack size exceeded
Asked Answered
C

5

25

This is my code.

var xhr = new XMLHttpRequest();
xhr.open('GET',window.location.href, true);
xhr.responseType = "arraybuffer";
xhr.onload = function(event) {
 debugger;
 console.log(" coverting array buffer to string "); 
 alert(String.fromCharCode.apply(null, new Uint8Array(this.response)));
};
xhr.send();

That request is being made to a PDF URL which is around 3 MB in size. I have read a few threads with same error, Maximum call stack size exceeded, telling me that there must be some recursive call but I do not see any recursive call here. Can anyone help?

Chickie answered 18/7, 2016 at 9:4 Comment(7)
Is this request to the very same page? Using GET on window.location.href?Alius
@Alius Yes.For example, the current page is cs.columbia.edu/~lok/3101/lectures/02-corejava.pdfChickie
If you call same page with same script included, why do you wonder there is too much recursion? Try calling other page with no script. Or if you call via xhr, than do not output the script again, or add parameter to distinct the call.Alius
@Alius this script wont execute in load function. I am just reading the pdf page data.Chickie
Have you tried to load other page, other pdf?Alius
@Alius Well, this code is inside extension. When people click an option this code gets execute. If the page is we pure html page, I am using jquery to get body text , where as for pdf url's I can use jquery body text. So reading the contents as arraybuffer and trying to parse it to a string. That is where I am getting this error.Chickie
Let us continue this discussion in chat.Chickie
D
32

I had the same problem and I finally used this code:

function _arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}
Dedradedric answered 20/3, 2020 at 22:54 Comment(2)
could use reduce instead, but this seems to be what is necessaryLanilaniard
this should be the accepted answer. works like a charmOakman
T
14

The error is caused by a limitation in the number of function arguments. See "RangeError: Maximum call stack size exceeded" Why?

Instead of String.fromCharCode.apply(), use e. g. a TextEncoder. See Uint8Array to string in Javascript

Tremolite answered 18/7, 2016 at 13:7 Comment(3)
Hi. How do you use the TextEncoder in my case? I have this var base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(blob)));Stink
I opened a separate questionStink
For a binary string TextEncoder is useless, it does not support Latin1 (it uses Windows−1252), you will get the broken result. (new TextDecoder("ISO-8859-1").decode(new Uint8Array([148]))).charCodeAt(0); // 8221, should be 148Garage
S
6
this.response.arrayBuffer()
              .then((buf) => {
                const uint8Array = new Uint8Array(buf);
                const data = uint8Array.reduce((acc, i) => acc += String.fromCharCode.apply(null, [i]), '');
                return data;
              })
Spreader answered 19/2, 2020 at 13:19 Comment(0)
B
1
Thank you so much Anthony O, you saved my 10 days work.
small modification in my scenario is:

Angular 7 :

/** Convert Uint8Array to string */

    private static arrayBufferToBase64( buffer: Uint8Array ) {
        var binary = '';
        var bytes = new Uint8Array( buffer );
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode( bytes[ i ] );
        }
        return  binary;
    }
Beadle answered 27/8, 2021 at 19:58 Comment(1)
Please don't add "thank you" as an answer. Instead, vote up the answers that you find helpful.Traject
E
1

A little bit more optimized variant would be to utilize the available stack size instead of converting each character separately.

var text = '';
for(var i = 0; i < Math.ceil(bytes.length / 32768.0); i++) {
  text += String.fromCharCode.apply(null, bytes.slice(i * 32768, Math.min((i+1) * 32768, bytes.length)))
}
Eugenle answered 12/5, 2023 at 22:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.