question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[FEATURE] Announce total length in HTTP header 'Content-Length'

See original GitHub issue

Thank you for your library. I was wondering if it is possible to calculate the download progress as a percentage. To do this, the response object of downloadZip() would have to contain the HTTP header Content-Length, which it does not at the moment.

I have already found that browsers hide HTTP headers from scripts on cross-origin requests (see here) unless the HTTP header Access-Control-Expose-Headers says otherwise. So, I adapted my server config to expose the Content-Length header. As a result, the request to fetch my test file returns the HTTP header Content-Length (see (1) in code snippet). But, because the HTTP header Content-Length is still missing on the response of downloadZip() (see (2) in code snippet), I cannot calculate a progress in percent (as the absolute value is unknown).

So my question is: is it even possible to include the HTTP header Content-Length and have it contain the sum of all content lengths of the files to be downloaded?

The following code snippet demonstrates how to observe the download progress:

import { downloadZip } from 'https://cdn.jsdelivr.net/npm/client-zip/index.js';

async function download() {

    /// (1) Original HTTP request where the Content-Length header is present
    const file = await fetch('https://4sc35swexhjkk3fe-public.s3-eu-west-1.amazonaws.com/elevator-music.mp3');

    const response = await downloadZip([file]);
    const reader = response.body.getReader();

    /// (2) Content-Length header is missing -> always 0 -> cannot calculate a relative progress
    const contentLength = +response.headers.get('Content-Length');

    let receivedLength = 0;
    const chunks = [];
    while (true) {
        const { done, value } = await reader.read();

        if (done) {
            break;
        }

        chunks.push(value);
        receivedLength += value.length;

        console.log(`Received ${receivedLength} of ${contentLength}`);
    }

    const blob = new Blob(chunks);

    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = 'test.zip';
    link.click();
    link.remove();
}

download();

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
Touffycommented, Mar 20, 2021

Hello. As I have explained in CONTRIBUTING.md, downloadZip does not set the content-length because it doesn’t know it when it returns the Response (at that point, it hasn’t even started to read the inputs). That is a consequence of the streaming design of the library.

It would be possible to set content-length without sacrificing memory efficiency if

  • you pass all your input in an array (not a generator), which forces you to fetch every input first (without reading the data)
  • every input has a known length (always true for Blobs and ArrayBuffers and strings, true for Responses if they have content-length themselves, and for other types — streams and iterators — it would requires adding a new optional property in the input object so you can announce the length manually)

Is that OK for you ?

Then of course downloadZip needs some new code to detect that every length is known in advance and to take advantage of it.

1reaction
Touffycommented, Apr 30, 2022

Should be solved with the newly published versions 1.5 (still distributed as ES2018 and without Zip64) and 2.2.

I must say the feature came at a significant cost in kilobytes (well, only about 1kB, but client-zip being so small to begin with, that was a big increase).

Read more comments on GitHub >

github_iconTop Results From Across the Web

HTTP headers | Content-Length - GeeksforGeeks
HTTP Content-Length entity-header is used to indicate the size of entity-body in decimal no of octets i.e. bytes and sent it to the...
Read more >
Content-Length - HTTP - MDN Web Docs
The Content-Length header indicates the size of the message body, in bytes, sent to the recipient.
Read more >
Is the Content-Length header required for a HTTP/1.0 response?
If it is not required for the response, how does the client read the response when it's larger than 1MB?
Read more >
HTTP/1.1: Header Field Definitions
The Age response-header field conveys the sender's estimate of the amount of time since the response (or its revalidation) was generated at the...
Read more >
Content-length header is not getting set in response to client
<FaultString>Error 0x01130024 Request did not match allowed-feature list</FaultString>. STAMMW ( ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found