4

All major browsers now support the DecompressionStream API, but I can't figure out how to use it with fetch() to decompress a gzip file in browser.

The following code works with a base64 string:

const decompress = async (url) => {
  const ds = new DecompressionStream('gzip');
  const response = await fetch(url);
  const blob_in = await response.blob();
  const stream_in = blob_in.stream().pipeThrough(ds);
  const blob_out = await new Response(stream_in).blob();
  return await blob_out.text();
};

decompress(
  'data:application/octet-stream;base64,H4sIAAAAAAAAE/NIzcnJVyjPL8pJAQBSntaLCwAAAA=='
).then((result) => {
  console.log(result);
});

However, if I create a hello.txt.gz file using gzip hello.txt on MacOS (hello.txt is a plain text file with content "hello world"), then the function above throws an Error.

decompress('/hello.txt.gz').then((result) => {
  console.log(result);
});
# FireFox
Failed to read data from the ReadableStream: “TypeError: The input data is corrupted: incorrect header check”.
Uncaught (in promise) DOMException: The operation was aborted.

# Chrome
Uncaught (in promise) TypeError: Failed to fetch

# Safari
[Error] Unhandled Promise Rejection: TypeError: TypeError: Failed to Decode Data.
[Error] Unhandled Promise Rejection: TypeError: Failed to Decode Data.

Edit

There is a reproducible demo at Stackblitz.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
Jay Wang
  • 2,650
  • 4
  • 25
  • 51
  • 1
    *"Failed to fetch"* - does the file accessible in the first place? – Bagus Tesa Jul 15 '23 at 01:27
  • It indeed looks like you're just hitting a 404 or alike. Check you path and your network tab. Also, from an URL like that you don't need to go to a Blob and then extract a stream from it, nor to produce a Blob from the Response to then get a text from it, you can directly do `const stream_in = response.body.pipeThrough(ds); return new Response(stream_in).text()` https://jsfiddle.net/yv5wzsrt/ – Kaiido Jul 15 '23 at 02:47
  • Thanks! @BagusTesa I added a demo at https://stackblitz.com/edit/vitejs-vite-vrvd2k?file=src%2Fmain.ts. The fetch response is 200. – Jay Wang Jul 15 '23 at 02:48
  • Hi @Kaiido, I added a demo at stackblitz.com/edit/vitejs-vite-vrvd2k?file=src%2Fmain.ts . It seems the fetch response is okay (200). Thank you so much for your example! It worked with my `hello.txt.gz` file! I will keep looking into it. – Jay Wang Jul 15 '23 at 02:52
  • 2
    Oh, that's interesting, but no, the response is not ok. The server sends the Content-Type as "text/plain" and the Content Encoding as "gzip", and it doesn't pass any data. Somehow the `.gz` extension makes it trip out in thinking it's one of its own response or something like that. Change the extension of your file e.g. to `.bin` and it will work fine. I'm really not sure why the server behaves like that, and I'm not sure either if it's only a stackblitz issue or if it's a default config. Just tried on my localhost (almost bare apache config) and it works fine, so that'd be a stackblitz issue. – Kaiido Jul 15 '23 at 02:55
  • Wow I see, thank you so much @Kaiido!! ❤️❤️ Changing to `.bin` worked for me. I guess there is something weird going on with the Vite server. They might be pre-processing files with extension `.gz`... – Jay Wang Jul 15 '23 at 03:03
  • @Kaiido Could you please add a short answer so I can accept it and close the problem? – Jay Wang Jul 15 '23 at 03:05
  • Related Vite issue: https://github.com/vitejs/vite/issues/12266 – Jay Wang Jul 15 '23 at 03:12
  • Oh I'm sorry I don't really have time right now to compose an answer, and the GH issue you found would make a far better answer than what I could have written, so feel free to self-answer :-) (Ps: I added retrospectively the vite issue for discoverability since this is actually the source of the issue). – Kaiido Jul 15 '23 at 04:59

1 Answers1

2

Thanks to @kaiido's help (see question comments), we found that this error is caused by the Vite server. The development server serve .gz files with wrong headers.

"content-encoding": "gzip"
​​"content-length": "42"
"content-type": "text/plain"

A workaround is to rename the file to use a different extension (e.g., hello.txt.gzhello.txt.gzip).

Related Vite Issues

Jay Wang
  • 2,650
  • 4
  • 25
  • 51