Guides / Prompting and shipping
How to Add File Uploads to Your App: Storage, Limits and Security
How to let users upload images and documents to your app: where files should live, size and type limits, private files, prompts to use, and common mistakes.
Mythex Team · · 5 min read
To add file uploads to your app, store the files in object storage (a bucket), not on your server's disk or in your database, and save a small record in the database with the file's key, name, size, type and owner. Check the file size and type on the server, decide up front whether files are public (like product photos) or private (like invoices), and serve private files only after checking who is asking. In an AI app builder, you can describe the upload feature in one prompt; the important part is testing that files survive a redeploy and can't be opened by the wrong person.
Decide what kind of uploads you need
Before building, answer three questions:
- What files? Profile photos, product images, PDFs, spreadsheets, audio, video. This decides type and size limits.
- Who can see them? Everyone (a public gallery) or only the uploader and admins (contracts, ID documents, client files).
- What happens after upload? Just store it, show a preview, resize images, or read the contents.
Public images and private documents need different setups, so settle this first.
Where files should live
| Option | How it works | Good for | Watch out for |
|---|---|---|---|
| Object storage (bucket) | Files stored in a service built for them; your database stores a key or URL | Almost every app | Access rules must be set correctly |
| Platform-provided storage | Your app builder or host enables a bucket for you | Apps built on that platform | Limits and pricing follow the platform |
| Server disk | Files written to the app server's filesystem | Local development only | Often wiped on restart or redeploy |
| In the database | File bytes stored in a table | Almost never | Bloats the database, slows backups |
| Third-party upload widget | A hosted uploader service handles the whole flow | Heavy media, image transforms | Another vendor, account and bill |
For most apps, object storage plus a database record is the right answer. The database row is what your app queries ("show this user's documents"); the bucket just holds the bytes.
Public vs private files
- Public files (product photos, blog images, avatars) can be served from a public URL. Anyone with the link can open them, which is fine for this kind of content.
- Private files (invoices, contracts, medical or ID documents, client deliverables) must never have a guessable public URL. The server checks that the logged-in user owns the file or has permission, then either streams it back or returns a signed URL: a link that works only for a short time.
A common and serious bug is private files stored in a public bucket with predictable names. Anyone who guesses /uploads/invoice-102.pdf gets someone else's invoice.
Example prompts
A public image upload:
Let admins upload up to 5 product photos per product. Accept JPG, PNG and WebP up to 5 MB each. Store the files in file storage, save each file's key, size and order in a product_images table, and show thumbnails with a remove button. Validate type and size on the server, not just in the browser.
A private document upload:
Add a Documents page for logged-in clients. Clients can upload PDFs up to 20 MB. Files are private: store them in file storage, save owner ID, original filename, size and upload time in a documents table, and only let the owner and admins download them. Downloads go through a server route that checks permission. Never expose a public URL for these files.
Useful follow-ups:
Show a progress bar during upload and a clear error if the file is too large or the wrong type.
When a document row is deleted, delete the stored file too.
Step by step
- Pick types and size limits for each upload field. Be specific: "PDF up to 20 MB", not "documents".
- Enable storage. In an AI builder, ask for uploads and it will set storage up; elsewhere, create a bucket and add its credentials as server-side secrets.
- Create a database table for file records: ID, owner, storage key, original name, type, size, created-at.
- Build the upload route on the server: check the user is logged in, check type and size, generate a safe storage key (not the user's filename), save the file, insert the record.
- Build the download or display path: public URL for public files; a permission-checked route or signed URL for private ones.
- Build the UI: file picker, drag and drop if useful, progress, previews, errors.
- Handle deletes so removing a record also removes the stored file.
- Test: upload, reload, redeploy or publish, and check the file still loads. Then log in as another user and try to open the first user's private file.
Common mistakes
- Writing uploads to the server's disk. It works in development, then files vanish after a restart or redeploy.
- Trusting the browser's checks. A file input's "accept" setting is a hint, not security. Check type and size on the server.
- Using the user's filename as the storage key. Names collide and can contain odd characters. Generate a unique key and store the original name separately.
- Public buckets for private files. See above; this is the one that makes the news.
- Allowing any file type. HTML or SVG files served from your domain can run scripts in some setups. Only accept the types you need.
- No size limit. One huge upload can eat your storage allowance or time out the request.
- Orphaned files. Deleting the database row but not the file slowly fills storage you're paying for.
- Forgetting mobile. Phone photos can be large and in formats like HEIC; decide whether to accept or convert them.
Checklist
- Files go to object storage, not the server disk or the database
- Each file has a database record with owner, key, name, type and size
- Type and size are checked on the server
- Storage keys are generated, not taken from the filename
- Private files are only served after a permission check
- Another user cannot open your private files, even with the link
- Deleting a record deletes the file
- Files still load after publishing or redeploying
- Upload errors are shown clearly, including on a phone
File uploads in Mythex
Mythex can enable file storage for a project automatically when your app needs uploads, so you don't provision a bucket by hand. You can also type /storage in chat. It's available on Free and Pro, with a 1 GB cap on Free, and you can see its status under Settings → Storage.
The docs are explicit that published hosting is not a durable local filesystem, so ask the agent to use platform storage rather than saving to disk. Stored files and downloads are paid from your credit balance, by size and by how much is downloaded; Pro pays half the Free rate. See File storage in the docs.
Uploads usually go hand in hand with a database for the file records and login for private files. If you're building a place where clients exchange documents, see how to build a client portal, and run through the security checklist before launch.
Questions
Where should uploaded files be stored?
In object storage (a service built for files, often called a bucket), not on the app server's disk and not inside the database. Store only the file's key or URL, plus details like name, size and owner, in your database.
Why do my uploaded files disappear after I publish or redeploy?
Most hosting platforms do not keep a durable local disk: when the app restarts or redeploys, files written to its disk are lost. Save uploads to object storage instead.
How do I keep uploaded files private?
Don't make the files publicly readable. Have your server check that the logged-in user is allowed to see a file, then send it or return a short-lived signed link to it.
Does Mythex support file uploads?
Yes. Mythex can enable file storage for a project when the app needs uploads, on Free and Pro, with a 1 GB cap on Free. You ask the agent for the upload feature or type /storage.