Next.js File Upload
Upload Files from Next.js Route Handlers and Server Actions
Upload files from Next.js route handlers or server actions. No SDK, REST API, CDN delivery.
Next.js gives you two clean server-side seams for file uploads — Route Handlers (app/api/.../route.ts) and Server Actions — and both can talk to files.link with the built-in fetch, no SDK. The advantage over Vercel Blob is that you are not married to one host: the same code runs on Vercel, Netlify, Railway, a container on CapRover, or a self-hosted Node server. The advantage over wiring up aws-sdk is that there is no IAM user, no bucket policy, and no SigV4 signing — just three fetch calls and an env var.
The non-negotiable rule: keep the API key server-side. It must never appear in a Client Component, a 'use client' file, or any NEXT_PUBLIC_ variable, or it ends up in the browser bundle. Route Handlers and Server Actions run only on the server, so process.env.FILESLINK_KEY stays safe there.
A Route Handler that proxies the upload:
// app/api/upload/route.ts
export async function POST(req: Request) {
const form = await req.formData();
const file = form.get('file') as File;
const key = process.env.FILESLINK_KEY!;
const r1 = await fetch(`https://api.files.link/v1/files/${process.env.FOLDER_ID}`, {
method: 'POST',
headers: { Authorization: key, 'Content-Type': 'application/json' },
body: JSON.stringify({ filesMetadata: [{ name: file.name, size: file.size, type: file.type }] }),
});
const { urls } = await r1.json();
const slot = urls[0];
await fetch(slot.url, { method: 'PUT', body: file });
await fetch('https://api.files.link/v1/files/confirm-upload', {
method: 'POST',
headers: { Authorization: key, 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: [slot.id] }),
});
return Response.json({ id: slot.id });
}The identical three-call sequence works inside a Server Action — mark the function 'use server', accept the FormData, and return the CDN URL to revalidate your UI. For very large files you can skip proxying the bytes through your server entirely: return the presigned PUT URL to the browser and let the client PUT directly to it, then call confirm-upload server-side.
That offloads bandwidth from your Vercel function and keeps you under serverless body-size limits. Files come back as CDN URLs, visibility is per file, storage is encrypted at rest, and billing is prepaid credits. For copy-paste code covering all three approaches, see the full step-by-step Next.js upload tutorial.
Benefits With No Complexity
Global CDN delivery
Edge-cached worldwide
Signed-URL security
What You Get
Unlimited files
Unlimited storage
Public + Private storage
CDN ready links
Prepaid credits
More coming soon
How files.link Works
1. Upload
2. Copy
3. Use Anywhere
Why Developers Choose files.link
A Better Way to Store & Deliver Files
| Vercel Blob | AWS S3 (aws-sdk) | files.link | |
|---|---|---|---|
| Runs on any host (not Vercel-locked) | |||
| No SDK — just built-in fetch | |||
| Direct browser→storage upload option | |||
| Global CDN delivery on every file | |||
| Prepaid credits (no surprise bills) |
Calculate Your Needs
Storage
Egress
CDN Bandwidth
Wire Up Next.js File Uploads
- Global CDN delivery
- Edge-cached worldwide
- Signed-URL security
- Unlimited files
- Unlimited storage
- Public + Private storage
- No subscription — prepaid credits keep spend predictable