Files
image-drop/README.md
2026-01-22 16:23:14 -07:00

6.4 KiB
Raw Blame History

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

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 SHA1 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:

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:

$ 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:

$ sudo docker compose down
$ sudo docker compose up --build -d

Updating

To update the code:

$ 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 peritem 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 SHA1 and checks a local SQLite cache (state.db) to prevent duplicates.
    • WebSocket /ws pushes peritem progress to the current browser session only.
  • Persistence: A local SQLite database (state.db) prevents reuploads across sessions. Uploaded files are stored in /data/uploads.

Setup

Requires Python 3.11+.

Create a venv, activate it, and install:

$ virtualenv -p python3 env
$ source env/bin/activate
(env) $ pip install -r requirements.txt
(env) $ cp .env.example .env
(env) $ vim .env

Run with live reload:

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 SHA1 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