I tested the loading of very large files with XMLHttpRequest and noticed an interesting behavior of Chrome (90.0.4430.212): It loads the full file, but finishes with a 200-OK code and and empty (!) result. First I thought it was a silent timeout or whatever, but no, it seems to be a reached memory limit.
Trying it in Firefox (13.0esr (64-bit)) took for ages, but in the end I knew more: The Transfer itself did not trigger an "error" or a "timeout" event, resulted with 200 and empty result as well. But it threw an error:
Exception { name: "NS_ERROR_OUT_OF_MEMORY", message: "", result: 2147942414, filename: "http://localhost/testcenter-backend/vo_data/teterei.html", lineNumber: 16, columnNumber: 0, data: null, stack: "transferComplete@http://localhost/testcenter-backend/vo_data/teterei.html:16:9\n" }
So it has nothing to do with the transport itself, but apparently a memory limit reached when trying to do anything with the result. When I don't use the oReq.response, the error does not appear.
Okay, how to handle this? In Firefox I can catch the error with a simple try catch block. But this does not work for Chrome. A naive approach would be just to check if the resulting content is empty, but I wonder if there is another possibility to detect this stuff happening.
--
How to reproduce:
- Create a huge file.
I generated a 10,4GB file this way:
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*10000]
- Run this code in a browser to load it.
const oReq = new XMLHttpRequest();
function updateProgress (oEvent) {
console.log("progress", oEvent.loaded);
}
function transferComplete(evt) {
console.log("The transfer is complete.", oReq.getAllResponseHeaders(), oReq.status);
console.log(oReq.response); // here too much memory is allocated
}
function transferFailed(evt) {
console.log("error", oReq.getAllResponseHeaders(), oReq.status);
}
function transferCanceled(evt) {
console.log("cancel", oReq.getAllResponseHeaders(), oReq.status);
}
function timeOut(evt) {
console.log("timeout", oReq.getAllResponseHeaders(), oReq.status);
}
oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.addEventListener("timeout", timeOut);
// your huge file here instead
oReq.open("GET", "https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"); // URL to huge file here
oReq.send();
The actual memory limit may vary to your system.