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?
Access-Control-Expose-Headersshould not be necessary (any more, that question you linked to is several years old) -Content-Lengthis a CORS-safelisted response header, meaning it gets exposed by default.content-encoding: gziphas something to do with the problem perhaps? Try and disable that, and see if anything changes.'accept-encoding': 'identity', and 'Content-type': 'text/plain'to deactivategzipbut nothing changed.