D
Deno

help

Better way to allow downloading of files besides serving entire file

Jjoshcantcode3/14/2023
I'm trying to allow users to download files that are in a private folder which cannot be accessed publicly. A special key is provided which allows them to download the file. Would I have to put the file into a public folder that can be accessed directly through a browser, or is there a way to use a router to serve files? I'm currently using a router to serve entire files to the client, but this creates a delay since some files can be gigabytes large and the site hangs while the file is being read + sent. I've attached a pic of how I serve files, any help would be appreciated! If I need to make a public folder called "download" instead, I can.
Jjoshcantcode3/14/2023
ctx.send doesn't seem to be working as intended either
IioB3/14/2023
I think the issue is that you're buffering the whole file into memory before sending it ideally it would be streamed Have you looked into https://deno.land/std@0.179.0/http/file_server.ts? I've never used oak before but I think this would solve a lot of your problems
Jjoshcantcode3/22/2023
Yeah this is the issue, I'm not sure how I could stream a file through Oak. I'll keep looking and I'll check out that link to see if I can figure it out, thank you! Oak's send method supposedly streams files, but whenever I try to stream it, it throws saying the response isn't writeable. But if I await the send, it goes back to the same behaviour I'm trying to avoid. send is obviously streaming but since the middleware returns, the response is closed. I'm still looking around Bumping this Bumping again, I've resorted to using an XMLHttpRequest to show the progress of the file transfer which helps with the frozen site appearance, but this isn't the behaviour I'm aiming for still
IioB3/22/2023
How big is this file?
Jjoshcantcode3/22/2023
It can be any size, from a couple mb to a couple gb The issue is when it's a couple gb, the entire file is sent to the client in a blob and that makes the site look like it froze when in reality it's waiting for the file And the file isn't in a public folder so I can't have the client redirect to it and download it normally
IioB3/22/2023
You definitely still could do a redirect just verify a cookie or something
Jjoshcantcode3/22/2023
The file is in a folder called "downloading", and it's not in a public folder so I can't do "https://<domain>/downloading/file.txt", that would return a 404. What I do instead is have a route that loads the file into a stream
.get("/download/:token", async (ctx) => {
const download = pendingDownloads.get(ctx.params.token);
if (!download) {
ctx.response.status = Status.NotFound;
return;
}

pendingDownloads.delete(ctx.params.token);

try {
const file = await Deno.open(`./downloading/${download}`);
const fileInfo = await file.stat();
ctx.response.headers.set('X-Decompressed-Content-Length', fileInfo.size.toString());
ctx.response.headers.set('Content-Disposition', `attachment; filename=${download}`);
ctx.response.type = "stream";
ctx.response.status = Status.OK;
ctx.response.body = streams.readableStreamFromReader(file);
} catch {
ctx.throw(Status.InternalServerError);
}
});
.get("/download/:token", async (ctx) => {
const download = pendingDownloads.get(ctx.params.token);
if (!download) {
ctx.response.status = Status.NotFound;
return;
}

pendingDownloads.delete(ctx.params.token);

try {
const file = await Deno.open(`./downloading/${download}`);
const fileInfo = await file.stat();
ctx.response.headers.set('X-Decompressed-Content-Length', fileInfo.size.toString());
ctx.response.headers.set('Content-Disposition', `attachment; filename=${download}`);
ctx.response.type = "stream";
ctx.response.status = Status.OK;
ctx.response.body = streams.readableStreamFromReader(file);
} catch {
ctx.throw(Status.InternalServerError);
}
});
DDoctor3/23/2023
If the site is giving a freezing effect then that’s a different issue with the JavaScript code downloading in sync instead of async. I think something like this should work.
const file = await Deno.open("some file")
ctx.response.body = file.readable
const file = await Deno.open("some file")
ctx.response.body = file.readable
Jjoshcantcode3/30/2023
The file doesn't seem to download at all with this approach. For reference I'm using the anchor element download method, unless there's a way to begin a streamed download on the client with another method I'm possibly just going to stick to showing the stream sending progress and then downloading the file all at once instead of it being a normal file download, it's not the behavior I want but I can't figure out how to get it to work regularly Only other thing I can think to do is stream the file's contents to the client during the file creation, but that seems like a hassle I found a way to pipe directly to the file system, only issue is that download progress isn't shown
const res = await fetch(`/download/${token}`);

const ws_dest = window.showSaveFilePicker().then(handle => handle.createWritable());

const ts_dec = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk);
}
});

return res.body.pipeThrough(ts_dec).pipeTo(await ws_dest);
const res = await fetch(`/download/${token}`);

const ws_dest = window.showSaveFilePicker().then(handle => handle.createWritable());

const ts_dec = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk);
}
});

return res.body.pipeThrough(ts_dec).pipeTo(await ws_dest);
Ended up going the route of public folders

Looking for more? Join the community!

Recommended Posts
Share state between islandsHi. How could I share state between island. E.g. shopping cart. I click on add product and in some oIslands not working with Cloudflare DNS proxyI have deployed Deno on a remote server with nginx-ingress-controller that offers self-signed certifUpdate sub-directory for module already added to deno.land/xThe title pretty much says it all, but the module in question is `hot_mod`, and the current subdir iShould we, or how should we, use Deno as a sandbox for untrusted code?I've been using Deno in this context because of some of the nice security model features. However, ideno_bindgen type error: deno-ts(2345)Anyone else getting this with `deno_bindgen`? > Argument of type 'bigint' is not assignable to paramUsing Rust FFI in a public Deno moduleI'm writing a Deno module that I intend to publish on deno.land. It will be using a Rust library (puPublishing to deno.land/x: GitHub webhook says it's delivered?I followed these directions (https://deno.land/add_module) to publish a 3rd party module to deno.lanDeno tsWhenever i run my deno file using a ts config like this documentation describes: https://deno.land/Nvim deno tsserver conflictmy language servers are conflicting when i open a deno project, if i use `LspInfo` i can see both deDeno Docker - deno run --watch file.tsI am on a macbook m1, and i tried to dockerize deno from the official image and whenever i try doingWebSocket subprotocolsThis might be a bug: Deno's websocket implementation seems to have issues with [subprotocols](https:How can I create a linked [ReadableStream,WritableStream] pair?Hi, I have a function A which accepts a WritableStream and another function B which accepts a Readabhow to use esbuild_deno_loader for local file?i have `[join(tmpDir, './bundle.js')]` as entry point (resulting as string e.g. `c:\Users\User\AppDawindow variable in fresh islandsHow do I access `window` in islands? I need to modify DOM code client side.Warning Implicitly using latest version (0.178.0) for...Hello - Deno newb here. When running `deno task start` I get "Warning Implicitly using latest verHow to prevent std/http from gzipping and overriding EtagIt appears deno std/http applies gzip content-encoding magically sometimes depending on the type of Fresh in a Docker exiting processNot sure whats going wrong. Works fine on deno deploy. But when trying to run it inside a docker coneval script with stricter permissions in denoHi all, I wanted to know if its possible to eval a script in deno with more strict permissions. Somesolid-js with DenoI was wondering if it was possible to use solid-js with Deno natively without something like esbuildFeature Suggestion: Dark Mode for `std` library Docs.Deno's documentation is great. I find myself reading it more and more. I currently use a browser add