-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify if ProgressEvent.loaded
should indicate the size of compress, or uncompressed, data
#388
Comments
Firefox is correct. This is actually defined in detail through the interaction with Fetch. Content codings are removed before the creation of a response stream. |
Thank you for replying. Would you be able to provide a link to where this is defined? I searched the Fetch spec for I'm also surprised the Fetch API has anything to do in XMLHttpRequest 🤔, considering Fetch came around more than a decade later? |
Because the response from the API is PHP output, the usual `Content-Length` header is absent. This [custom header technique](https://stackoverflow.com/questions/15097712/how-can-i-use-deflated-gzipped-content-with-an-xhr-onprogress-function/32799706#32799706) allows the client to know the total length of the data being received, in order to display a progress indicator. Here's a code example with `XMLHttpRequest`: ``` xhr.addEventListener("progress", (e) => { if (e.lengthComputable) { onDownloadProgress({ loaded: e.loaded, total: e.total, }); } else { const uncompressedContentLength = xhr.getResponseHeader( "X-Uncompressed-Content-Length", ); if (uncompressedContentLength) { onDownloadProgress({ loaded: e.loaded, total: Number(uncompressedContentLength), }); } } }); ``` Notes: - `Fetch` can be used as well, however it doesn't allow to track the progress of uploaded data (when creating a paste); whereas `XMLHttpRequest` does. - `e.loaded` can be different between browsers; Firefox reports the length of the compressed data, Chrome reports the length of uncompressed data (see whatwg/xhr#388). A workaround for this is to manually set our progress indicator to 100% when the request finishes.
Because the response from the API is PHP output, the usual `Content-Length` header is absent. This [custom header technique](https://stackoverflow.com/questions/15097712/how-can-i-use-deflated-gzipped-content-with-an-xhr-onprogress-function/32799706#32799706) allows the client to know the total length of the data being received, in order to display a progress indicator. Here's a code example with `XMLHttpRequest`: ``` xhr.addEventListener("progress", (e) => { if (e.lengthComputable) { onDownloadProgress({ loaded: e.loaded, total: e.total, }); } else { const uncompressedContentLength = xhr.getResponseHeader( "X-Uncompressed-Content-Length", ); if (uncompressedContentLength) { onDownloadProgress({ loaded: e.loaded, total: Number(uncompressedContentLength), }); } } }); ``` Notes: - `Fetch` can be used as well (only reason I use `XMLHttpRequest` is because `fetch` doesn't allow to track the progress of uploaded data (when creating a paste); whereas `XMLHttpRequest` does). - `e.loaded` can be different between browsers; Firefox reports the length of the compressed data, Chrome reports the length of uncompressed data (see whatwg/xhr#388). A workaround for this is to manually set our progress indicator to 100% when the request finishes.
What is the issue with the XMLHttpRequest Standard?
When a
ProgressEvent
fires,ProgressEvent.loaded
contains the size of the data already transmitted.If the data is compressed and its total size is unknown, then, depending on the browser,
ProgressEvent.loaded
can contain either the size of the compressed data, or the size of the decompressed data.It would be great if the spec could clarify which of these two values should be the one provided by
ProgressEvent.loaded
.Additional context
With a response containing compressed data and unknown total size (the
Content-Length
header is not set),ProgressEvent.lengthComputable
isfalse
andProgressEvent.total
is not usable, preventing us from displaying a progress indicator.In this case, a common technique is to set a custom response header
X-Uncompressed-Content-Length
containing the size of the uncompressed data being transmitted.We can then, on the client side, use the value of this header as a substitue of
ProgressEvent.total
, and display a progress indicator with the value ofProgressEvent.loaded
divided by the value of this header.However, depending on the browser,
ProgressEvent.loaded
can be either the size of the compressed data already transmitted (the case in Firefox), or, the size of the decompressed data already transmitted (the case in Chrome).For example:
loaded
, shows a total of 1345276 at the end.loaded
, shows a total of 1017454 at the end.The text was updated successfully, but these errors were encountered: