I tried various days to make a progress bar for my download, a task which I expected to be quite trivial.
Everything seemed to to be just right, but the event.total
-value was always 0 (or undefined
in the angular-version.
This is basically how the file got passed:
<?php // backend.php
if (isset($_GET["file"])) {
$file = "dlstuff/{$_GET["file"]}";
}
$stream = fopen($file, 'rb');
header('Content-Length: '. filesize($file));
header("Content-Type: text/plain", true);
fpassthru($stream);
And the header was exposed in .htaccess
as stated here:
Header add Access-Control-Expose-Headers "Content-Length"
I obtained the file with Javascript like this: The application was written in angular, but I could reproduce it with simple plain HTML:
const oReq = new XMLHttpRequest();
oReq.addEventListener("progress", oEvent => {
console.log("progress");
console.log({ loaded: oEvent.loaded, total: oEvent.total, status: oReq.status });
console.log(oReq.getAllResponseHeaders());
});
oReq.addEventListener("load", () => {
console.log("complete");
console.log({ status: oReq.status, downloaded: oReq.response.length });
console.log(oReq.getAllResponseHeaders());
});
oReq.open("GET", "http://localhost/backend.php?file=whatever.htm");
oReq.send();
I read a lot of stuff
- XMLHttpRequest "total" returns 0 when fetching JSON
- How can I access the Content-Length header from a cross domain Ajax request?
- Content-length and other HTTP headers?
- Content-Length header with HEAD requests?
But still - no event.total
and the Content-Length
was not visible in the browser-console.
progress
(index):11 {loaded: 65536, total: 0, status: 200}
(index):12 access-control-expose-headers: Content-Length
connection: Keep-Alive
content-encoding: gzip
content-type: text/plain;charset=UTF-8
date: Mon, 13 Sep 2021 15:09:22 GMT
keep-alive: timeout=5, max=99
server: Apache/2.4.38 (Debian)
transfer-encoding: chunked
vary: Accept-Encoding
I started to loose my mind overt this until I changed the Content-Type
-header in the PHP-Script to application/pdf
by accident. Suddenly it worked!
What it going on? The real application may have various file formats but I would like to treat them all as text from the Javascript side.
--
Edit 1:
`application/octet-stream``instead of Pdf works as well. But the question remains: why?