Upload Flow
Upload a file by passing the binary data along with organization and metadata options:What happens during upload
Size validation
The file is checked against
MAX_FILE_SIZE (default: 50 MB). Empty files are rejected.Filename sanitization
The filename is cleaned to prevent path traversal and restricted to safe characters:
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
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.
Temporary Files
Upload files with an expiration time for temporary use cases like export downloads or preview links:Configuration
| Variable | Description | Default |
|---|---|---|
AWS_REGION | AWS region for S3 | us-east-1 |
AWS_ACCESS_KEY_ID | S3 access key | - |
AWS_SECRET_ACCESS_KEY | S3 secret key | - |
S3_ENDPOINT | Custom S3 endpoint (for R2, MinIO) | - |
S3_BUCKET | S3 bucket name | bunship-files |
S3_FORCE_PATH_STYLE | Use path-style URLs (required for MinIO, R2) | false |
MAX_FILE_SIZE | Maximum upload size in bytes | 52428800 (50 MB) |

