I'm building an app which among other things has the ability to upload files to an existing API. This API takes both file metadata and contents in a JSON object, so I need to convert the binary contents of the files to base64 encoded strings.
Since this is a potentially heavy operation, I moved the functionality into a web worker. The worker takes in an ArrayBuffer object with the binary file contents (returned from FileReader.readAsArrayBuffer()), and returns a base64 encoded string.
This works fine for smaller files, but for the largest files I need to support (~40 MB) this causes out of memory exceptions for my worker (8007000E in Internet Explorer). On rare occasions it goes through, but most of the time the worker just dies. The same happened before moving it into the worker, except then the entire browser page crashed (both in IE and Chrome). Chrome seems to be a bit more resilient to the memory strain in workers than IE is, but I still have to make it work properly in IE (10+).
My worker:
onmessage = e => {
const bytes = new Uint8Array(e.data);
const l = bytes.length;
const chars = new Array(l);
for (let i = 0, j = l - 1; i <= j; ++i, --j) {
chars[i] = String.fromCharCode(bytes[i]);
chars[j] = String.fromCharCode(bytes[j]);
}
const byteString = chars.join('');
const base64bytes = btoa(byteString);
try {
postMessage(base64bytes, [base64bytes]);
} catch (e) {
postMessage(base64bytes);
}
};
Am I making some big no-nos here? Are there any ways to reduce the memory consumption? One solution I've thought about would be to process the contents in chunks rather than the whole file, then concatenate the resulting strings and encode it on the outside. Would that be viable, or will that cause problems of its own? Are there any other magical functions I don't know about? I had a glimmer of hope with FileReader.readAsBinaryString(), but it's now removed from the standard (and not supported in IE10 anyway) so I can't use it.
(I realize this question could be relevant at Code Review too, but since my code is actually crashing, I figured SO was the correct place)
charsstarting from each end and finishing in the middle?