Serving Files
Files can be served privately (through a server endpoint) or publicly (direct S3 URL).
Private Files
Create a SvelteKit endpoint that streams files through the server. This allows access control:
// routes/files/[fileId]/+server.ts
import type { RequestHandler } from './$types'
import { serverFileManager } from '$lib/files.server'
export const GET: RequestHandler = async ({ params }) => {
return await serverFileManager.streamFile(params.fileId)
}
streamFile returns a Response with headers for Content-Type, Content-Length, Content-Disposition (inline), and Cache-Control (private, 1 hour).
Public Files
For files that don't need auth, make the bucket public and serve directly from S3.
Make a Bucket Public
// On creation
await serverFileManager.createBucket('public-bucket', { public: true })
// Or after the fact
await serverFileManager.makeBucketPublic('public-bucket')
This applies an S3 bucket policy allowing public GetObject access.
Client File Manager
Generate public URLs on the client:
// lib/files.client.ts
import { env } from '$env/dynamic/public'
import { ClientFileManager } from '@repo/storage'
export const clientFileManager = new ClientFileManager({
s3: {
endpoint: env.PUBLIC_S3_ENDPOINT,
},
})
const url = clientFileManager.getClientFileUrl({
key: file.key,
bucket: file.bucket,
})
// => "https://s3.example.com/public-bucket/abc-123.png"
Returns undefined if the input is undefined.