Skip to content

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

bun-file-share

A small file sharing app built only on Bun's built-in APIs. Files are streamed into an S3 bucket (MinIO locally) as they are uploaded, image uploads get a WebP thumbnail, every file has a presigned download link, and a whole folder can be downloaded as one archive. File metadata lives in a local SQLite database.

Run it

You need Docker for the local S3 bucket and Bun 1.4 or newer.

bun install
cp .env.example .env
docker compose up -d        # MinIO on :9000 (API) and :9001 (console), bucket "files" created for you
bun run dev                 # http://localhost:3000 with hot reload

Other scripts:

bun start                   # run without hot reload
bun test                    # unit tests; the integration test runs too when S3_ENDPOINT is set
docker compose down -v      # stop MinIO and delete its data

To use different host ports for MinIO set MINIO_PORT and MINIO_CONSOLE_PORT before docker compose up, and point S3_ENDPOINT at the new API port.

Environment variables (see .env.example):

Variable Default Meaning
PORT 3000 HTTP port
S3_ENDPOINT http://localhost:9000 S3 compatible endpoint (MinIO, R2, AWS...)
S3_BUCKET files Bucket name
S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY minioadmin Credentials
S3_REGION us-east-1 Region used for signing
MAX_UPLOAD_BYTES 52428800 Largest accepted upload request (50 MB)
DATABASE_PATH data/files.sqlite Where file metadata is stored

Presigned download URLs point at S3_ENDPOINT, so that host has to be reachable from the browser. With the bundled Docker setup that is http://localhost:9000, which works when you open the app on the same machine.

Routes

Route What it does
GET / The page: upload form, folder filter, file list with thumbnails
POST /api/upload Multipart form with files (one or more) and optional folder; streams each file into S3
GET /api/files?folder= List files, optionally for one folder, plus the list of folders
GET /api/files/:id Metadata for one file
DELETE /api/files/:id Remove the object, its thumbnail and the metadata row
GET /api/files/:id/url JSON with a presigned GET URL valid for one hour
GET /d/:id 302 redirect to that presigned URL
GET /api/files/:id/thumb 200px wide WebP thumbnail, streamed from the bucket
GET /api/folders/:folder/archive All files in the folder as <folder>.tar.gz

Bun.Archive writes tar archives (optionally gzipped) and does not produce zip files, so the folder download is a .tar.gz. Every desktop OS can open those.

Bun APIs used

Bun API Where
Bun.serve with routes and typed req.params src/server.ts:20
HTML import served as a bundled page src/server.ts:1, src/server.ts:26
new S3Client({ endpoint, bucket, ... }) src/storage.ts:10
s3.file(key).writer() multipart streaming upload src/storage.ts:25
s3.write(key, bytes, { type }) src/storage.ts:44
s3.presign(key, { method, expiresIn, contentDisposition }) src/storage.ts:58
s3.delete(key) src/storage.ts:66
s3.file(key).stream() as a Response body src/server.ts:76
s3.file(key).bytes() src/server.ts:141
Bun.Image resize and WebP encode src/storage.ts:40
Bun.Archive with gzip src/server.ts:143
Bun.randomUUIDv7() src/server.ts:115
bun:sqlite with prepared statements src/db.ts:21, src/db.ts:38
Response.redirect to a presigned URL src/server.ts:67

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages