A Windows desktop file-sharing server with a Tkinter launcher, FastAPI backend, browser clients, role/group permissions, and an auditable local data model.
The Tkinter window starts a local uvicorn service, shows user/admin URLs and QR codes, and lets you select the save directory. Phones, tablets, and computers on the same trusted Wi-Fi or LAN can then upload, browse, download, and package files from native HTML/CSS/JavaScript pages.
The service listens on 0.0.0.0 by default. This makes LAN access possible and also exposes the service to every reachable network. Run it only on a trusted network.
- Streams uploaded bytes without transcoding, recompression, image/video rewriting, EXIF changes, or extension changes.
- Stores size and SHA-256; attempts to preserve browser-provided
File.lastModifiedvalues. - Supports raw downloads, single-file ZIP, selected/batch ZIP, search, and server-side sorting.
- Uses guest, user, and admin roles. Guests see only files in the
publicgroup. - Signed-in users can upload and delete their own files; admins manage all files, users, groups, visibility, and audit history.
- Creates built-in
publicandeveryonegroups for a new save directory. - Creates an initial administrator account:
admin / 12345678. - Recursively redacts password, token, session, authorization, cookie, and secret fields from audit metadata.
- Provides Chinese/English browser UI with the preference stored in
localStorage. - Uses a Tkinter desktop lifecycle controller rather than a background system service.
Change the default administrator password immediately after first launch. The default password exists only to initialize a new local save directory.
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m lan_transfer.desktopThe desktop app displays two addresses:
- User URL for guests and ordinary users.
- Admin URL for administrator sign-in and management.
Wait until the desktop status reads Running, then open a URL or scan its QR code from a device on the same LAN.
- Start the desktop app and choose a save directory.
- Open the Admin URL and sign in with the initial account on a new directory.
- Change the administrator password before sharing the User URL.
- Create individual users or up to 200 ordinary users in one validated batch; create groups and assign memberships.
- Upload files or folders and choose their visibility groups.
- Use search/sort and raw or ZIP download from another LAN device.
- Review audit events for login, logout, upload, download, delete, permission, account, and group changes.
Mobile browsers do not always apply an HTTP Last-Modified value to the downloaded file on disk. Use ZIP download when preserving the archive entry mtime is important.
- Guests can list/download only
publicfiles and cannot upload or delete. - Ordinary users can see files assigned to their groups, upload files, and delete only their own uploads.
- Admins can manage accounts/groups, set file
allowed_groups, inspect audits, and delete all files. - The built-in
publicandeveryonegroups and the built-inadminaccount cannot be deleted. - Deleting a user transfers that user's existing files to
adminso a future account with the same name cannot inherit deletion rights. - A group cannot be deleted while any user or file references it.
User and administrator endpoints are deliberately separate. A same-origin admin cookie must never enlarge what the User page can list or download.
The selected save directory contains uploaded files and local control data:
manifest.json
.lan-transfer-auth.json
.lan-transfer-audit.jsonl
These control names, their temporary variants, and unsafe absolute/parent paths are reserved by path validation. Uploads use chunked .part files, size verification, SHA-256, nonconflicting names, mtime application, and atomic publication. Manifest and auth updates use hidden randomized temporary files and atomic replacement.
Strongly audited operations are transactional:
- a pending upload is invisible until its audit entry and manifest publication both succeed;
- audit failure rolls back login/logout, password, account, group, upload, delete, and permission changes;
- deletion uses a recoverable tombstone until manifest and audit work can commit;
- unsafe or stale manifest paths are revalidated before list, download, ZIP, delete, or rollback use.
.\.venv\Scripts\python.exe -m pytest
node --check .\lan_transfer\static\user.js
node --check .\lan_transfer\static\admin.jsTests cover authentication, lockout, account/group permissions, batch creation, visibility, search/sort, byte integrity, mtime, response headers, ZIP behavior, paths, duplicate names, transaction rollback, audit redaction, desktop lifecycle, logging, release metadata, and frontend contracts.
No dedicated lint or format command is declared. The two node --check commands are JavaScript syntax checks.
powershell -ExecutionPolicy Bypass -File .\scripts\build_exe.ps1The script installs dependencies, runs tests, and builds a windowed one-file executable with PyInstaller.
dist\LANFileTransfer.exe
release-assets\LANFileTransfer.exe
release-assets\lan-file-transfer-v1.0.0-windows.zip
release-assets\SHA256SUMS.txt
No MSI is generated because there is no WiX, Inno Setup, or NSIS definition. Release binaries are not digitally signed; Windows may show an unknown-publisher warning. Download from the project Release page and verify SHA256SUMS.txt.
| Path | Responsibility |
|---|---|
lan_transfer/desktop.py |
Tkinter window, QR codes, save-directory selection, and service lifecycle |
lan_transfer/server.py |
uvicorn thread startup, health, timeout, and shutdown |
lan_transfer/api.py |
FastAPI routes, role/session boundaries, visibility, sorting, downloads, and error mapping |
lan_transfer/auth.py |
Accounts, groups, PBKDF2 password hashes, sessions, IP lockout, and auth persistence |
lan_transfer/storage.py |
Streamed files, manifest, hash/mtime, ZIP, ownership, visibility, transactions, and tombstones |
lan_transfer/security.py |
Upload and stored-manifest path normalization/containment |
lan_transfer/audit.py |
Redacted JSONL audit trail |
lan_transfer/config.py |
Save directory, available port, LAN address, and URLs |
lan_transfer/static/ |
Native user/admin browser applications |
tests/ |
Backend, desktop, release, and frontend-contract regression suites |
- Passwords are locally hashed with PBKDF2; session values and passwords must never be returned in JSON, validation errors, logs, or audit metadata.
- Five failed logins from one IP trigger a three-hour lockout.
- The service is HTTP on the LAN, not HTTPS. Network peers may be able to observe traffic; use only a trusted network.
- Guest-visible
publicfilenames and files are intentionally reachable without sign-in. - Raw download headers include integrity/cache/mtime metadata, but browsers control the final filesystem timestamp.
- Do not expose the listener through port forwarding, public Wi-Fi, a public firewall rule, or an untrusted VPN.
- Keep route policy in
api.py, accounts and sessions inauth.py, file transactions instorage.py, and path validation insecurity.py; add focused regression coverage in the correspondingtests/test_*.pysuite. - Browser changes must preserve the separate user/admin contracts, Chinese/English strings, stale-response guards, and native no-CDN frontend. Run both
node --checkcommands after editing JavaScript. - Re-run permission, path, audit, rollback, and byte-integrity tests whenever a change crosses more than one backend module; a successful UI action alone does not prove the disk and audit state committed together.
- Dependency changes require an update to the open-source audit. Release changes must rebuild, launch, inspect the portable archive, and verify metadata and checksums.
- Keep all three README versions aligned and retain the HTTP, trusted-LAN, default-password, public-file, mtime, and unsigned-binary warnings.
MIT © 2026 HaoXiang Huang.