MDZelo
首页/Indie Hacker Guide/File Upload System

File Upload System

Many SaaS products need file upload: avatars, images, PDFs, contracts, attachments, spreadsheets, audio, video, and import files.

File upload looks like a form feature, but in production it touches file size, format validation, storage path, permissions, security scanning, progress, retry, CDN, deletion policy, and cost.

If the first design is too casual, the system becomes difficult to maintain when files grow.

Do Not Store Files Directly in the Database

A common beginner mistake is storing file content directly in the database.

Databases are good for structured data: users, orders, projects, and file records. They are not good for large binary files. The actual file should live in object storage such as S3, R2, OSS, COS, or GCS.

The database stores metadata:

text
file_id
owner_id
bucket
object_key
file_name
mime_type
size
status
created_at

The database knows who owns the file, where it is, and what state it is in. Object storage stores the actual content.

Do Not Expose Business Structure in Paths

Object storage paths should be designed carefully.

Do not use the original filename as the unique path, and do not put sensitive business information directly into the path. Original filenames can duplicate, contain special characters, or expose private information.

Prefer system-generated keys:

text
uploads/{user_id}/{file_id}/{safe_file_name}

Or:

text
uploads/{yyyy}/{mm}/{file_id}

You can display the original filename to users, but storage paths should be controlled by the system.

Prefer Presigned Upload

Many early systems upload files to the business server first, then transfer them to object storage.

This is simple, but large files create bandwidth and memory pressure on your server. Presigned upload is usually better.

Flow:

text
1. Frontend asks backend for upload credentials
2. Backend checks user permission and file info
3. Backend creates presigned URL
4. Frontend uploads directly to object storage
5. Frontend notifies backend after upload
6. Backend updates file status

The file data does not pass through your business server, making the system more stable and resource efficient.

Validate Before and After Upload

Do not trust the file sent by the frontend.

Validate file size, extension, MIME type, business limits, user quota, upload frequency, and file count. Frontend validation improves user experience. Backend validation protects the system. Object storage policies can also restrict size and type.

Examples:

text
Avatar: jpg/png/webp only, max 5MB
PDF: application/pdf only, max 20MB
Import sheet: csv/xlsx only, max 10MB
Video: limit format, size, and duration

Clear validation rules reduce dirty data later.

Uploaded Does Not Mean Ready

A successful upload only means the file reached storage. It does not mean the file is usable.

Many files need post-processing: image compression, thumbnail generation, virus scan, PDF parsing, audio/video transcoding, spreadsheet parsing, or content safety checks.

The file table should have status:

text
pending_upload
uploaded
processing
ready
failed
deleted

After upload, show “processing” first, then mark it ready when background work finishes.

Design File Permissions Separately

File permissions cannot rely only on hidden URLs.

For private files, access should first go through your business system to check permissions, then generate a temporary access URL or return the file through a controlled download endpoint.

Common permission issues:

text
User A accesses user B's file
Team member accesses files from deleted projects
Public share link exposes private files
Removed member can still access old files
Temporary URL lasts too long

Files often contain private and business data. Permission design must be more careful than normal pages.

Separate Public and Private Files

Not all files need to be private.

Public avatars, cover images, and article images can live in a public bucket or CDN. Contracts, invoices, import data, user attachments, and internal documents should be private.

Public files optimize speed and caching. Private files optimize permission safety and auditability.

Do not mix all files into one permission model.

Progress and Retry Matter

File upload is different from a normal form. Users wait.

If a large upload has no progress, cancel button, or failure message, users do not know whether the system is stuck.

At minimum, provide:

text
Upload progress
Uploading state
Failure message
Retry upload
Cancel upload
Size limit hint
Format limit hint

Clear upload experience reduces support issues.

Deletion Needs a Policy

When a user deletes a file, should it be removed from object storage immediately?

It depends on the business. Many systems soft-delete the database record first, then clean object storage asynchronously. This prevents accidental deletion and leaves room for recovery and audit.

Consider:

text
Can users restore deleted files?
Is the file referenced by multiple objects?
Does object storage have lifecycle rules?
Do orphan files need scheduled cleanup?
Do audit records need to be kept?

File deletion is not just delete, especially in team and paid products.

Estimate Cost Early

File system cost is not only storage.

It also includes upload traffic, download traffic, CDN traffic, image processing, video transcoding, request count, backup, and cross-region replication.

If your product allows large files or videos, cost can rise quickly. Set size limits, quotas, and cleanup rules early.

Do not wait for a surprising bill before adding upload limits.

A File Upload Architecture

Use this structure:

text
Frontend:
Select file / validate / progress / retry

Backend:
Permission check / create file record / presigned URL / confirm upload

Object storage:
Original file / access control / lifecycle

Background jobs:
Scan / compress / parse / transcode / thumbnail

Database:
Metadata / status / owner / permission / business relation

This is closer to a real system than “one upload endpoint.”

Final Thoughts

The key to file upload is not uploading the file. It is defining clear rules for upload, storage, processing, access, deletion, and audit.

The recommended early structure is: object storage for files, database for metadata, presigned URL for direct upload, background jobs for processing, and separate permission control for access.

Next, we continue with storage choices: How to Choose Image Storage.

评论

0

分享你对这一章的想法

还没有评论成为第一个分享想法的人。