From 8c251aae7ff61fab5c2d8e44df8e2fc67e3addf2 Mon Sep 17 00:00:00 2001 From: Nulo Date: Sun, 10 Dec 2023 17:52:54 -0300 Subject: [PATCH] WIP: un intento de evitar streamsaver si es posible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no me genera mucha confianza este código pero era para prevenir usar streamsaver cuando no lo necesitamos con un hack en el servidor si está disponible --- frontend/src/lib/fetch.ts | 69 ++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/frontend/src/lib/fetch.ts b/frontend/src/lib/fetch.ts index ae2f5b0..729af21 100644 --- a/frontend/src/lib/fetch.ts +++ b/frontend/src/lib/fetch.ts @@ -1,4 +1,3 @@ -import streamSaver from "streamsaver"; import { zData, type Distribution, zError, zDumpMetadata } from "common/schema"; export async function downloadFile( @@ -7,36 +6,62 @@ export async function downloadFile( dist: Distribution, ) { if (!dist.downloadURL) throw new Error("no downloadURL"); - const outputS = streamSaver.createWriteStream( - dist.downloadURL.slice(dist.downloadURL.lastIndexOf("/") + 1), - ); - const res = await fetchGzipped( - `${dataPath}/${datasetId}/${dist.identifier}/${ - dist.fileName || dist.identifier - }.gz`, - ); - await res.body!.pipeTo(outputS); + const downloadURL = `${dataPath}/${datasetId}/${dist.identifier}/${ + dist.fileName || dist.identifier + }.gz`; + + const localGzip = async () => { + const streamSaver = await import("streamsaver"); + const outputS = streamSaver.createWriteStream( + dist.downloadURL!.slice(dist.downloadURL!.lastIndexOf("/") + 1), + ); + const res = await fetchGzipped(downloadURL); + await res.body!.pipeTo(outputS); + }; + + if (navigator.userAgent.indexOf("Firefox") != -1) { + // firefox, por alguna razón inexplicable, no entiende el `content-encoding` + // cuando se intenta descargar un archivo. lo ignora y guarda el archivo + // comprimido. entonces tenemos que usar el hack de streamsaver. prefiero + // usarlo solo en firefox porque anda medio mal o no anda en otros navegadores. + await localGzip(); + } else { + const infoRes = await fetch(downloadURL); + await infoRes.body?.cancel(); + if (infoRes.headers.get("Content-Type") === "application/gzip-hack") { + // server tiene el hack de gzip=true activado, genial + location.href = `${downloadURL}?gzip=true`; + } else { + await localGzip(); + } + } } async function fetchGzipped(url: string): Promise { - let res = await fetch(url); + let res = await fetch(`${url}?gzip=true`); if (res.status === 404 && url.endsWith(".gz")) { // probar cargando el archivo no comprimido res = await fetch(url.slice(0, url.length - ".gz".length)); return res; } - let DecStream; - if ("DecompressionStream" in window) DecStream = window.DecompressionStream; - else { - const { makeDecompressionStream } = await import( - "compression-streams-polyfill/ponyfill" - ); - DecStream = makeDecompressionStream(TransformStream); + if (res.headers.get("Content-Type") === "application/gzip-hack") { + // server tiene el hack de gzip=true activado, genial + return res; + } else { + // server no tiene el hack, usamos DecompressionStream + let DecStream; + if ("DecompressionStream" in window) DecStream = window.DecompressionStream; + else { + const { makeDecompressionStream } = await import( + "compression-streams-polyfill/ponyfill" + ); + DecStream = makeDecompressionStream(TransformStream); + } + const ds = new DecStream("gzip"); + const decompressedStream = res.body!.pipeThrough(ds); + const resD = new Response(decompressedStream); + return resD; } - const ds = new DecStream("gzip"); - const decompressedStream = res.body!.pipeThrough(ds); - const resD = new Response(decompressedStream); - return resD; } let cachedGzippedJson = new Map();