|
| 1 | +# Image Uploader API |
| 2 | + |
| 3 | +FastAPI application that stores uploaded files to disk, tracks them with SQLModel, and serves them back through a lightweight CDN-like interface. |
| 4 | + |
| 5 | +## Features |
| 6 | +- Protected upload and listing endpoints secured with an API key header. |
| 7 | +- Files stored with generated UUID names while preserving the original name for metadata. |
| 8 | +- Optional background cleaner that prunes files older than a configured retention window. |
| 9 | +- SQLite by default, with configurable database URL via environment variables. |
| 10 | + |
| 11 | +## Getting Started |
| 12 | + |
| 13 | +```bash |
| 14 | +python3 -m venv venv |
| 15 | +source venv/bin/activate |
| 16 | +pip install --upgrade pip |
| 17 | +pip install -r requirements.txt |
| 18 | +``` |
| 19 | + |
| 20 | +Create a `.env` (or export environment variables) with at least: |
| 21 | + |
| 22 | +``` |
| 23 | +API_KEY=choose-a-strong-secret |
| 24 | +``` |
| 25 | + |
| 26 | +Optional settings: |
| 27 | + |
| 28 | +| Variable | Default | Description | |
| 29 | +|----------|---------|-------------| |
| 30 | +| `UPLOAD_DIR` | `./uploads` | Directory for stored files. Created automatically. | |
| 31 | +| `DB_URL` | `sqlite:///./cdn.db` | SQLModel database URL. Use a server DB in production. | |
| 32 | +| `DELETE_AFTER_HOURS` | `72` | Retention window for cleanup. | |
| 33 | +| `CORS_ORIGINS` | `*` | Comma-separated list of allowed origins. | |
| 34 | +| `ENABLE_CLEANER` | `true` | Disable (`false`) to skip scheduling the cleanup job. | |
| 35 | + |
| 36 | +Run the API: |
| 37 | + |
| 38 | +```bash |
| 39 | +./run.sh |
| 40 | +# or |
| 41 | +uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2 --proxy-headers |
| 42 | +``` |
| 43 | + |
| 44 | +## API Overview |
| 45 | + |
| 46 | +All protected endpoints require the header `x-api-key: <API_KEY>`. |
| 47 | + |
| 48 | +| Method | Path | Description | |
| 49 | +|--------|------|-------------| |
| 50 | +| `POST` | `/upload` | Accepts multipart file upload, stores file, returns metadata (`id`, `url`, `size`, `type`). | |
| 51 | +| `GET` | `/list` | Returns list of stored files with original name, size, and creation timestamp. | |
| 52 | +| `GET` | `/{filename}` | Serves a stored file by UUID filename as returned by `/upload`. | |
| 53 | + |
| 54 | +Returned `url` values are relative (e.g. `/3d4d...jpg`), suitable for prefixing with your CDN/API host. |
| 55 | + |
| 56 | +## Cleaning Expired Files |
| 57 | + |
| 58 | +If `ENABLE_CLEANER` is `true`, a background APScheduler job runs hourly to delete files older than `DELETE_AFTER_HOURS`. The job removes both the file on disk and its database row. |
| 59 | + |
| 60 | +## Development & Testing |
| 61 | + |
| 62 | +Run the unit tests (requires dependencies from `requirements.txt`): |
| 63 | + |
| 64 | +```bash |
| 65 | +pytest |
| 66 | +``` |
| 67 | + |
| 68 | +The test suite spins up the FastAPI app against a temporary SQLite database to cover: |
| 69 | +- API key enforcement on uploads. |
| 70 | +- Upload/list/serve happy path. |
| 71 | +- Directory traversal hardening for file serving. |
| 72 | + |
| 73 | +## Deployment Notes |
| 74 | + |
| 75 | +- Ensure `API_KEY` is always set in your deployment environment—startup fails otherwise. |
| 76 | +- When using SQLite, the app configures thread-safe connection settings. For higher concurrency, consider a PostgreSQL or MySQL instance and update `DB_URL`. |
| 77 | +- Mount or back up `UPLOAD_DIR` storage if files need to persist beyond the cleaner retention window. |
0 commit comments