Upload Flow
Upload a file by passing the binary data along with organization and metadata options:What happens during upload
1
Size validation
The file is checked against
MAX_FILE_SIZE (default: 50 MB). Empty files are rejected.2
Filename sanitization
The filename is cleaned to prevent path traversal and restricted to safe characters:
3
S3 key generation
Files are stored with an organization-scoped key to ensure tenant isolation:
4
Upload to S3
The file is uploaded with the appropriate MIME type and cache headers.
- Public files:
Cache-Control: public, max-age=31536000(1 year) - Private files:
Cache-Control: private, no-cache
5
Database record
A record is created in the
files table with the file ID, S3 key, bucket, size, MIME type, and metadata.Response
Storage Backends
BunShip uses the AWS SDKS3Client, which supports any S3-compatible service. Configure the backend through environment variables:
- AWS S3
- Cloudflare R2
- MinIO (local dev)
Presigned URLs
Generate time-limited download URLs for private files. The default expiration is 15 minutes:404 Not Found error.
File Management
List files
Retrieve files for an organization with optional MIME type filtering and pagination:Get file metadata
getSignedUrl to generate a download link.
Delete files
BunShip supports both soft delete and hard delete:includeDeleted: true to include them.
Check existence
Verify a file exists in both the database and S3:Path Traversal Protection
Filenames are sanitized before use as S3 keys. The service strips directory traversal sequences and restricts characters:{orgId}/{fileId}/{name}), which prevents one organization from accessing another’s files even if a collision were to occur.

