7

I want to allow my users to download a text file.

How would I go about this in Remix?

I tried exposing the txt file via a resource route, but then the user navigates away from the page. But I'd the file to just download, or maybe have them pick a download location. In any case, I want the user to stay on the page.

asked Feb 21, 2023 at 21:49

2 Answers 2

8

I just had to figure out how to do this for an app that I am building.

In short, you will need to set Content-Disposition header to "attachment". This forces the download.

Then you will to construct a response that streams the document that you want to be dowloaded.

Here is an end to end example:

import { createReadableStreamFromReadable } from '@remix-run/node';
import { Readable } from 'node:stream';
export const loader = async () => {
 const file = createReadableStreamFromReadable(
 Readable.from(['Hello, World!']),
 );
 return new Response(file, {
 headers: {
 'Content-Disposition': 'attachment; filename="hello.md"',
 'Content-Type': 'text/markdown',
 },
 });
};

Here I use Readable.from(['Hello, World!']) to construct the file, but this could be fs.readFile, etc.

You place all of this in a _route.ts of your choice.

When linking to this resource route from the app, you will need to add reloadDocument attribute to the link, e.g.

<Link to="/download" reloadDocument />

This forces the use of browser navigation instead of client-navigation.

answered Nov 22, 2023 at 13:04
Sign up to request clarification or add additional context in comments.

1 Comment

This helped me out. I'm using cloudflare workers and it worked with jszip. createReadableStreamFromReadable is non existent, but this piece of code worked: const filename = "example.txt"; const content = "Hello, this is a test file."; // Create a zip file const zip = new JSZip(); zip.file(filename, content); const zipContent = await zip.generateAsync({ type: "blob" }); return new Response(zipContent, { headers: { "Content-Type": "application/zip", "Content-Disposition": 'attachment; filename="files.zip"', }, });
1

If you use a standard a tag, you can trigger a download if you add the download attribute to it => https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download

You can then link to the resource route that produces the txt file and the download should work as expected.

Maybe this even works with the Remix/ReactRouter Link component, but I’m just on the phone currently so cannot test this. Anyways, a standard anchor tag should work.

answered Feb 21, 2023 at 22:22

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.