download wf update
This commit is contained in:
@@ -10,6 +10,8 @@ database, no object storage, and no queue. Expired files are swept automatically
|
||||
## Features
|
||||
|
||||
- Drag & drop / file-picker uploads with progress, straight from the browser.
|
||||
- **Media files render inline** (image/video/audio/PDF/text) as direct, embeddable
|
||||
links, with one-click **Direct / HTML / BBCode / Markdown** link formats.
|
||||
- **Optional per-file password**: set a password to gate downloads behind a prompt.
|
||||
- Storage on the local filesystem; files survive restarts.
|
||||
- A cryptographically secure, unguessable download key for every file.
|
||||
@@ -131,10 +133,11 @@ curl -F "password=hunter2" -F "[email protected]" http://localhost:3000/api/uploa
|
||||
{
|
||||
"id": "u8wcfcm7",
|
||||
"key": "u8wcfcm7",
|
||||
"url": "/u8wcfcm7",
|
||||
"url": "/u8wcfcm7.zip",
|
||||
"originalName": "example.zip",
|
||||
"downloadName": "u8wcfcm7.zip",
|
||||
"size": 123456,
|
||||
"mimeType": "application/zip",
|
||||
"protected": true
|
||||
}
|
||||
```
|
||||
@@ -161,9 +164,10 @@ curl -sS -F "[email protected]" "$BASE/api/upload"
|
||||
{
|
||||
"id": "u8wcfcm7",
|
||||
"key": "u8wcfcm7",
|
||||
"url": "/u8wcfcm7",
|
||||
"url": "/u8wcfcm7.zip",
|
||||
"originalName": "myfile.zip",
|
||||
"size": 123456,
|
||||
"mimeType": "application/zip",
|
||||
"protected": false
|
||||
}
|
||||
```
|
||||
@@ -210,13 +214,20 @@ Keep `id`/`key` around to delete the file afterwards via `DELETE /api/files/:id`
|
||||
|
||||
### `GET /:key` (also `HEAD`)
|
||||
|
||||
The download URL is just the key at the site root (`https://host/u8wcfcm7`).
|
||||
The legacy `/d/:key` form still works as an alias. A file without a password
|
||||
streams immediately; if a password is set, the server shows a password prompt
|
||||
before streaming. A wrong or non-existent key returns a generic `404`.
|
||||
The download URL is the key at the site root, optionally with the file extension
|
||||
appended for a Catbox-style link (`https://host/u8wcfcm7` or
|
||||
`https://host/u8wcfcm7.zip`). The legacy `/d/:key` form still works as an alias. A
|
||||
file without a password streams immediately; if a password is set, the server shows
|
||||
a password prompt before streaming. A wrong or non-existent key returns a generic
|
||||
`404`.
|
||||
|
||||
Media files (images, video, audio, PDF, plain text) are served `inline` so they
|
||||
render directly in the browser and can be embedded (`<img>`, Discord, etc.).
|
||||
Everything else — and any URL with `?dl=1` — is sent as an `attachment` download.
|
||||
|
||||
```bash
|
||||
curl -O http://localhost:3000/u8wcfcm7 # streams, or prompts if password set
|
||||
curl -O http://localhost:3000/u8wcfcm7 # streams, or prompts if password set
|
||||
curl -O "http://localhost:3000/u8wcfcm7.zip?dl=1" # always force a download
|
||||
```
|
||||
|
||||
### Password protection
|
||||
@@ -279,9 +290,11 @@ paths or stack traces.
|
||||
`../`, encoded traversal, null bytes, and symlink injection via user input are
|
||||
not possible.
|
||||
Downloads additionally refuse symlinks (`lstat`) as defense in depth.
|
||||
- **MIME / XSS.** Downloads are sent as `Content-Disposition: attachment` (browsers
|
||||
download rather than render) with `X-Content-Type-Options: nosniff`, so a spoofed
|
||||
`text/html` or `image/svg+xml` cannot execute scripts.
|
||||
- **MIME / XSS.** Non-media downloads are sent as `Content-Disposition: attachment`
|
||||
(browsers download rather than render) with `X-Content-Type-Options: nosniff`, so a
|
||||
spoofed `text/html` or `image/svg+xml` cannot execute scripts. Only a whitelist of
|
||||
inert media types (image, video, audio, PDF, plain text — never HTML or SVG) is
|
||||
served `inline` for direct/embed links.
|
||||
- **Secrecy of URLs.** All responses carry `Referrer-Policy: no-referrer`, and
|
||||
downloads use `Cache-Control: private, no-store`, so the keyed URL is not leaked
|
||||
to referrers or shared caches.
|
||||
|
||||
Reference in New Issue
Block a user