Streaming files in Next.js App Router
Basic file serving with the public folder
It’s very common to allow the users of a website to download static files.
Images are the most common type of static files, your website probably has a logo or a picture somewhere on the homepage. You may also share your CV in PDF format, your startup pitch deck, the recipe for the best lasagna…
The /public
folder of Next.js apps allows for the sharing of static files.
But as the name implies, files in this folder are available to anyone.
How can we handle private or bigger files?
Advanced file streaming use cases
This pattern covers the following advanced use cases:
- Private files: You want to check some permissions before serving “extremely_confidential_report.docx”.
- Personalized files: A generic url “/user/profile-picture” may serve a different image depending on the currently logged-in user.
- Generated files: The State of JavaScript survey backoffice app generates CSV exports of the current responses. This means that we generate the file on the fly when we receive an export request.
We can’t use the /public
folder for that. We have to craft a more elaborate API endpoint to serve the files.
In Next.js App Router, we call API endpoints “Route Handlers”.
Let’s stream a file from a route handler.
🔨 Practice: how to stream a file from a route handler
Take a look at the codebase. It demonstrates a page displaying an image that should be streamed from a route handler.
If you want to skip practice, you can jump to the solution using the “solve” button above the code.
Warning: this exercise consists of adding a single line into the code, but don’t be fooled: this is considered a very difficult pattern! You can jump straight to the solution using the dedicated button.
- If you are not yet familiar with Route Handlers, start by reading the official documentation.
- Read the documentation for Node.js
filehandle.readableWebStream
- Use this function to transform the file stream into a webstream. You will need the “bytes” option.
- The image should appear on the website.
- Close the file using experimental
next/after
(/!\ will not work with Next 14, only Next 15)
References
I previously wrote articles about streaming files, using a custom function. Special thanks to Karl Horky for showing me a simpler approach.
Node.js GitHub issue related to using readableWebStream in Next.js
How to stream files from Next.js Route Handlers - ericburel.tech
French version of this article - formationnextjs.fr
Next.js official doc about streaming in Route Handlers
NextPatterns is currently in its beta-test phase. Want to join? Reach out to me on X (ericbureltech) or at support@nextpatterns.dev
- Installing dependencies
- Starting http server