# File Drop Uploader A self-hosted web app for uploading files and media and saving them to the filesystem on your server. Useful for letting people upload vacation photos, etc. just by sending them a link. Admin user can create invite links with optional limits and password protection. A public uploader page is optional and enabled by default. [View Screenshots](screenshots.md) ## Features - **Local Saving:** All uploaded files are saved to the server's local filesystem. - **Drag and Drop:** Upload multiple files and folders by dragging them onto the page. - **Invite Links:** Create sharable links for uploads; one-time or multi-use. - **Manage Links:** Search/sort, enable/disable, delete, edit name/expiry. - **Passwords (optional):** Protect invite links with a password. - **Albums:** Upload into a specific folder (auto-create supported). Preserves client-side folder structure on upload. - **Duplicate Prevention:** Local SHA‑1 cache prevents re-uploading the same file. - **Telegram Notifications (optional):** Get notified via Telegram when upload batches are complete. - **Progress Queue:** WebSocket updates; see upload progress in real-time. - **Chunked Uploads (optional):** Large-file support with configurable chunk size. - **Mobile + Dark Mode:** Responsive UI, safe-area padding, persistent theme. ## Quick start Clone the repo. Copy `.env.example` to `.env` and edit. ### Docker Compose Create `docker-compose.yml` and edit: ```yaml services: file-drop: build: . container_name: file-drop restart: unless-stopped ports: - "8080:8080" env_file: - .env volumes: - ./data:/file_drop/data - /mnt/example/file-drop:/file_drop/data/uploads healthcheck: test: ["CMD-SHELL", "python - <<'PY'\nimport urllib.request,sys\ntry:\n urllib.request.urlopen('http://localhost:8080/').read(); sys.exit(0)\nexcept Exception:\n sys.exit(1)\nPY"] interval: 30s timeout: 5s retries: 3 start_period: 10s ``` Start the service: ```bash $ sudo docker compose up --build -d ``` Set up nginx / a reverse proxy and point it to the web app. Make sure it allows WebSocket connections through, for example: ``` server { root /var/www/html; index index.html index.htm; server_name upload.example.com; listen 80; client_max_body_size 100M; location / { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # websockets proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; } } ``` Then restart nginx and set up HTTPS: ``` $ sudo service nginx restart $ sudo certbot --nginx ``` ### Config Changes If you change the `.env` file config, simply run: ```bash $ sudo docker compose down $ sudo docker compose up --build -d ``` ### Updating To update the code: ```bash $ sudo docker compose down $ git pull --rebase $ sudo docker compose up --build -d ``` ### Telegram Bot An optional Telegram bot can send you notifications when uploads complete. This is useful to see if random people are filling your disk up. To create a bot, message @BotFather on Telegram. Come up with a name and username. Botfather will then send you an API key you can paste into the `.env` config directly. Next you'll need to find your own Telegram user ID. You can message @userinfobot and it will reply with your ID. Be ware of impersonator bots (they have the name "userinfobot" but a different username). Then message the bot you just created "/start" so that it's able to interact with you. ### Chunked Uploads - Chunked uploads are enabled by default. Uses setting `CHUNKED_UPLOADS_ENABLED=true`. - Configure chunk size with `CHUNK_SIZE_MB` (default: `50`). The client only uses chunked mode for files larger than this. - Intended to bypass upstream proxy limits (e.g., 100MB) while preserving duplicate checks, EXIF timestamps, album add, and per‑item progress via WebSocket. ## Developtment ### Architecture - **Frontend:** static HTML/JS (Tailwind). Drag & drop or "Choose files", queue UI with progress and status chips. - **Backend:** FastAPI + Uvicorn. - Saves uploaded files to the local filesystem. - Computes SHA‑1 and checks a local SQLite cache (`state.db`) to prevent duplicates. - WebSocket `/ws` pushes per‑item progress to the current browser session only. - **Persistence:** A local SQLite database (`state.db`) prevents re‑uploads across sessions. Uploaded files are stored in `/data/uploads`. ### Setup Requires Python 3.11+. Create a venv, activate it, and install: ```text $ virtualenv -p python3 env $ source env/bin/activate (env) $ pip install -r requirements.txt ``` ```text (env) $ cp .env.example .env (env) $ vim .env ``` Run with live reload: ```bash python main.py ``` ### How it works 1. **Queue** - Files selected in the browser are queued; each gets a client-side ID. 2. **De-dupe (local)** - Server computes **SHA‑1** and checks `state.db`. If seen, marks as **duplicate**. 3. **Save** - The file is saved to the local filesystem under `./data/uploads`. 4. **Album** - If an album is specified via an invite link, or a folder name is provided on the public page, the file is saved into a corresponding subdirectory. Client-side folder structure is also preserved. 5. **Progress** - Backend streams progress via WebSocket to the same session. 6. **Privacy** - The UI shows only the current session's items. It does not provide a way to browse saved files. ### Security notes - The menu and invite creation are behind login. Logout clears the session. - Invite links are public by URL; share only with intended recipients. - The public uploader page at `/` is enabled unless disabled with `PUBLIC_UPLOAD_PAGE_ENABLED=false`. - No browsing of uploaded media; only ephemeral session state is shown. - Run behind HTTPS with a reverse proxy and restrict CORS to your domain(s). ## License This program is free and open-source software licensed under the MIT License. Please see the `LICENSE` file for details. That means you have the right to study, change, and distribute the software and source code to anyone and for any purpose. You deserve these rights. ## Acknowledgements This project was forked from "Immich Drop Uploader" by Simon Adams: https://github.com/Nasogaa/immich-drop