From 802ed6df71c8f2d8e8a63e110f1db3a754e3ccbc Mon Sep 17 00:00:00 2001 From: Lendemor Date: Tue, 9 Apr 2024 18:41:58 +0200 Subject: [PATCH] cleaner way to download files, use modern fetch API --- reflex/.templates/web/utils/state.js | 34 ++++++++++++++++++++-------- reflex/staticfiles.py | 4 ++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index 59f63c360..cc95d2fba 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -159,19 +159,33 @@ export const applyEvent = async (event, socket) => { } if (event.name == "_download") { - const a = document.createElement("a"); - a.hidden = true; - // Special case when linking to uploaded files (when rx.download is returned from upload_files handler.) - a.href = event.payload.url.replace( + const getFilenameFromUrl = (url) => url.split("/").pop().split("?")[0]; + + // if the URL come from an upload handler, replace the backend URL placeholder with the actual backend URL + const downloadUrl = event.payload.url.replace( "${getBackendURL(env.UPLOAD)}", getBackendURL(env.UPLOAD) ); - if (event.payload.filename) { - a.href = a.href + "?filename=" + event.payload.filename; - } - a.download = event.payload.filename; - a.click(); - a.remove(); + const filename = event.payload.filename || getFilenameFromUrl(downloadUrl); + fetch(downloadUrl, { + method: "GET", + headers: { "X-Filename": filename }, + }) + .then((response) => { + if (!response.ok) + throw new Error(`Download of file at ${downloadUrl} failed`); + return response.blob(); + }) + .then((blob) => { + const blobURL = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + console.log("Downloading file from ", blobURL, " as ", filename); + a.href = blobURL; + a.download = filename; + a.click(); + window.URL.revokeObjectURL(blobURL); + }) + .catch((error) => console.log(error)); return false; } diff --git a/reflex/staticfiles.py b/reflex/staticfiles.py index d929eec79..13ddde72d 100644 --- a/reflex/staticfiles.py +++ b/reflex/staticfiles.py @@ -20,8 +20,8 @@ class UploadedFiles(StaticFiles): The response for the static file with download headers. """ req = Request(scope) - if "filename" in req.query_params: - filename = req.query_params["filename"] + if "x-filename" in req.headers: + filename = req.headers["x-filename"] content_disposition = f'attachment; filename="{filename}"' else: content_disposition = "attachment"