Open Source File Uploader — And the Storage Behind It
Open Source File Uploader: Keep the UI, Rent the Storage
Uppy, Dropzone and FilePond give you the upload UI for free. They do not give you somewhere to put the bytes. files.link is the storage, direct links and global CDN underneath your open-source uploader — plain REST, prepaid usage pricing, no per-seat plans.
Open source file uploader
Search for an open source file uploader and you land on the same shortlist: Uppy, Dropzone, FilePond, react-dropzone, filepond-plugin-*. They are genuinely good software, they are free, and you should probably use one. What none of them ship — because it isn't their job — is somewhere for the bytes to land. An uploader is a UI plus a transport; it needs an endpoint at the other end that stores the file, gives it a URL, and serves that URL fast to whoever asks.
That missing half is what teams underestimate, and it's where the weekend project turns into a quarter of infrastructure work: a bucket, IAM policies, a presigning endpoint, a CDN distribution, cache rules, signed URLs for the private files, a retention story, and a bill with a separate egress meter on it.
So treat this as a layers question rather than a versus question. files.link is not an open source file uploader and does not pretend to be one — it is a commercial, closed-source storage and delivery service with a plain REST API. It ships no widget, no script tag, and no vendor component in your bundle. You keep Uppy or whichever uploader you already like, and it points at an endpoint of yours that speaks to files.link underneath.
The uploader stays yours to style, localize, and version; the storage, the direct file links, and the global CDN across 450+ edge locations stop being your problem.
The wiring is short. Your backend calls POST /v1/files/{folderId} with the file's metadata and gets back a presigned PUT URL plus a file id; the browser PUTs the bytes straight to that URL, so a 2 GB video never streams through your API process; then POST /v1/files/confirm-upload with the id finalizes it and the file is live on a CDN URL. Auth is the raw API key in the Authorization header — no Bearer prefix, no SDK.
For large files there is a real multipart path too: POST /v1/files/multipart/{folderId}/initiate returns per-part presigned URLs, and /v1/files/multipart/complete finishes the job — which is precisely the shape Uppy's @uppy/aws-s3 multipart plugin expects, so the integration is a getUploadParameters function pointing at your own route rather than a rewrite.
In Next.js that route is a handful of lines in an app-router route handler; in React it's whatever fetch call you already make. The API key stays on the server — only the presigned URL reaches the browser.
Be clear about what you don't get, because picking this pairing on a wrong assumption wastes real time. There is no tus support, so Uppy's @uppy/tus resumable-across-sessions transport does not apply here; multipart lets a large upload retry a failed part, which is not the same guarantee. There is no Companion equivalent either — the piece of Uppy's stack that pulls files from Dropbox, Google Drive, or Instagram via OAuth is a server you'd still run yourself.
No on-the-fly image transformations, no virus scanning, and no upload UI of any kind. And files.link is a paid service on prepaid credits: storage, delivery, and API requests draw from one balance that auto-recharges, rather than a free tier. If your requirement is that every layer be auditable open-source code you can self-host, then the honest answer is MinIO or a bucket you own — not this.
What you're buying instead is the thing that's tedious to keep running. Files get permanent direct links that survive renames and folder moves, private files get no public URL at all and are reached through signed links that expire (10 minutes by default, up to 7 days), delivery is CDN-backed by default rather than a distribution you configure, and there's one prepaid balance instead of separate storage, request, and egress meters to reconcile after the month closes.
If you're weighing a hosted widget product instead of an open-source one, the trade-offs are laid out in the Uploadcare, Filestack, UploadThing and Transloadit comparisons — worth noting that Uppy is maintained by Transloadit, so the free uploader and the paid processing backend are already designed as two layers by the same people. Ours is the same split with a different backend.
Uppy on the front, files.link underneath
Wire an Open-Source Uploader to a Backend You Don't Have to Run
The uploader is the easy half. This is the other half — what happens between the user dropping a file and a URL you can put in an <img> tag, using only endpoints that exist today.
1. Keep the uploader you already chose
Uppy, Dropzone, FilePond, react-dropzone — none of them change. files.link ships no widget and no component, so there is nothing to swap in your bundle and nothing to restyle. The uploader keeps owning drag-and-drop, previews, progress bars, i18n and validation, which is the part it is genuinely better at than any vendor widget you'd otherwise embed.
2. Add one route on your server that mints the upload URL
Your route calls POST /v1/files/{folderId} with the file metadata and gets back { url, id }. Return just the url to the browser. The API key never leaves your server, and Uppy's @uppy/aws-s3 `getUploadParameters` hook is exactly the seam this plugs into. See the file upload API and the upload a file guide for the full request shapes.
3. Let the browser PUT straight to storage
The uploader sends the bytes to the presigned URL directly, so a large file never proxies through your API process and never counts against your app server's memory or request timeout. For multi-gigabyte files use POST /v1/files/multipart/{folderId}/initiate instead — it returns a presigned URL per part, matching Uppy's multipart mode, and a failed part retries on its own rather than restarting the upload. There is no tus endpoint, so resume-after-browser-close is not on the table.
4. Confirm, then use the link
POST /v1/files/confirm-upload with the id (or /v1/files/multipart/complete for multipart) and the file is live. Public files get a permanent CDN URL that keeps resolving through renames and folder moves. Private files get no public URL at all — your backend mints a signed link when an authorized user asks, defaulting to 10 minutes and settable up to 7 days.
5. Stop maintaining the plumbing
No bucket policies to review, no CDN distribution to configure, no egress line to forecast separately. Storage, delivery and API requests draw from one prepaid balance that auto-recharges. Framework specifics live in the Next.js, React and Node.js writeups.
Is this pairing the right fit?
- You want to keep an open-source uploader UI and only outsource the backend.
- Your developer file upload flow needs a stable public URL or an expiring private one.
- Large uploads should go browser-to-storage, not through your API process.
- You'd rather not own a bucket, a CDN distribution and a presigning service.
- One prepaid balance beats reconciling storage, request and egress meters.
- You do NOT need every layer to be self-hosted open source — if you do, run MinIO.
Honest scope
files.link is not open source and ships no upload widget — you keep Uppy or its equivalent for the UI. There is no tus support, no Uppy Companion equivalent for OAuth remote sources like Dropbox or Google Drive, no image transformations, and no virus scanning. It is a paid service on prepaid credits, not a free tier. Uploading requires an activated account; downloading a public link never does.
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
| Uppy + your own S3 | Uppy + Transloadit | Uploadcare | files.link | |
|---|---|---|---|---|
| Open-source, self-hostable end to end | ||||
| Keep your own uploader UI (no vendor widget) | ||||
| Storage, CDN and presigning you don't operate | ||||
| Presigned multipart for large files | ||||
| tus resumable uploads | ||||
| OAuth remote sources (Drive/Dropbox) without running Companion | ||||
| On-the-fly image transformations | ||||
| Single prepaid balance, no separate egress meter |
Calculate Your Needs
Storage
Egress
CDN Bandwidth
Give Your Uploader a Backend
- Global CDN delivery
- Edge-cached worldwide
- Signed-URL security
- Unlimited files
- Unlimited storage
- Public + Private storage
- No subscription — prepaid credits keep spend predictable