File Drop
A P2NS plugin for temporary, peer-to-peer file sharing. Upload a file, get a link, share it. Files automatically expire after 24 hours.
Features
- 24-Hour Expiration: Files are automatically deleted after 24 hours
- Destroy on Download: Optional one-time download - file is deleted after first download
- Peer-to-Peer: Files are stored in Hyperdrive and replicated across the P2NS network
- No Size Limits: Limited only by your storage (though large files take longer to replicate)
- Shareable Links: Each upload gets a unique link like
/d/abc123def - Modern UI: Clean, responsive dark theme interface
How It Works
Architecture
File Drop uses two P2NS data stores:
-
Hyperdrive (
uploads): Stores the actual file data- Each peer has their own writable drive
- Files are replicated to other peers on demand
-
HyperDB (
@filedrop/files): Stores file metadata- File ID, name, size, MIME type
- Upload timestamp and expiration time
- Drive key (so other peers know where to find the file)
- Destroy-on-download flag
Upload Flow
- User uploads a file via the web interface
- File is written to the local Hyperdrive
- Metadata (including the drive key) is stored in HyperDB
- HyperDB replicates metadata to all peers
- User receives a shareable link
Download Flow
- User visits the download link
- Plugin looks up file metadata in HyperDB
- If the file is local, reads from local drive
- If the file is remote, opens the uploader's drive by key and fetches
- If "destroy on download" is enabled, file is deleted after serving
API Endpoints
POST /api/upload
Upload a file. Accepts multipart/form-data.
Form Fields:
file(required): The file to uploaddestroyOnDownload(optional): Set to"true"to delete after first download
Response:
{
"success": true,
"id": "abc123def",
"filename": "document.pdf",
"size": 102400,
"mimeType": "application/pdf",
"expiresAt": 1702684800000,
"destroyOnDownload": false,
"link": "/d/abc123def"
}
GET /api/download/:id
Download a file by ID. Returns the file with appropriate Content-Type and Content-Disposition headers.
GET /api/file/:id
Get file metadata without downloading.
Response:
{
"id": "abc123def",
"filename": "document.pdf",
"size": 102400,
"mimeType": "application/pdf",
"uploadedAt": 1702598400000,
"expiresAt": 1702684800000,
"expiresIn": 86400000,
"isLocal": true
}
GET /api/files
List all active (non-expired) files.
Response:
{
"files": [...],
"count": 5
}
GET /d/:id
Human-friendly download page with file info and download button.
Configuration
The plugin is configured via config.json:
{
"name": "File Drop",
"version": "1.0.8",
"domain": "file.drop",
"enabled": true,
"www": "www",
"hyperdb": {
"schemas": {
"namespace": "filedrop",
"structs": [
{
"name": "files",
"fields": [
{ "name": "id", "type": "string", "required": true },
{ "name": "filename", "type": "string", "required": true },
{ "name": "size", "type": "uint", "required": true },
{ "name": "mimeType", "type": "string", "required": true },
{ "name": "driveKey", "type": "string", "required": true },
{ "name": "destroyOnDownload", "type": "bool", "required": false },
{ "name": "uploadedAt", "type": "uint", "required": true },
{ "name": "expiresAt", "type": "uint", "required": true }
]
}
]
},
"collections": [
{
"name": "files",
"schema": "@filedrop/files",
"key": ["id"]
}
]
}
}
File Structure
file.drop/
├── config.json # Plugin configuration and HyperDB schema
├── index.js # Backend logic (upload, download, cleanup)
├── README.md # This file
├── www/
│ ├── index.html # Upload interface
│ └── css/
│ └── style.css
├── db/ # HyperDB data (auto-generated)
├── drives/ # Hyperdrive data (auto-generated)
└── spec/ # Generated HyperDB schema files
Usage
- Navigate to
https://file.drop(or your configured internal domain) - Drag and drop a file, or click "Choose File"
- Optionally check "🔥 Destroy after download" for one-time links
- Share the generated link
- Recipients can download until the file expires or is destroyed
Notes
- Files uploaded on one peer are accessible to other peers via Hyperdrive replication
- The uploader's peer must be online for remote peers to download (unless the file has been cached)
- Cleanup runs hourly to remove expired files
- The "destroy on download" feature only works when downloaded from the uploader's peer
- This plugin is skipped on master nodes (
"disable_on_master": trueinconfig.json)
License
MIT