mcpField
S
serverpod-file-uploads

serverpod-file-uploads

github.com/serverpodDevelopment3.3k45 installsUpdated 1d ago
Repository

About serverpod-file-uploads

Serverpod File Uploads is a reference skill for implementing file uploads in Serverpod applications. It guides developers through server-issued upload descriptions, client uploads, verification, storage access, and backend choices.

Key features

  1. 01Server-issued upload descriptions
  2. 02Client-side uploads with FileUploader
  3. 03Post-upload verification
  4. 04Public and temporary download URLs
  5. 05Database and cloud storage backends

Use cases

  1. 01Adding profile image uploads
  2. 02Accepting large files as streams
  3. 03Serving time-limited private downloads
  4. 04Choosing a storage backend for production

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/serverpod/serverpod --skill serverpod-file-uploads

After installing, type/serverpod-file-uploadsin Claude Code to confirm it loaded.

Details

From the project README

Serverpod File Uploads

Flow: server issues upload description → client uploads → server verifies. Default storage is the database; use S3, GCP, R2, or compatible object storage for production.

Server: create upload description

Future<String> getUploadDescription(Session session, String path) async {
  return await session.storage.createUploadDescription(
    storageId: 'public',
    path: path,
  );
}

Always authorize the request and derive the path from trusted server-side state (user id, tenant id, object id). Do not accept arbitrary client paths.

Server: verify upload

Future<bool> verifyUpload(Session session, String path) async {
  return await session.storage.verifyUpload(
    storageId: 'public', path: path);
}

Always verify after client upload when using object storage.

Client: upload

var desc = await client.myEndpoint.getUploadDescription('profile/$userId/avatar.png');
var uploader = FileUploader(desc);
await uploader.upload(byteDataOrStream);
await client.myEndpoint.verifyUpload('profile/$userId/avatar.png');

Use Stream for large files. Paths: no leading slash, object-store compatible, normalized, and scoped to the authenticated user/tenant.

Security checklist

  • Require authentication/authorization for both description and verification endpoints.
  • Validate or derive content type, size, and extension before issuing descriptions.
  • Never let clients choose cross-tenant paths or storage IDs.
  • Store metadata in your database after verifyUpload succeeds.

Accessing stored files

  • session.storage.fileExists(storageId: 'public', path: path)
  • session.storage.publicDownloadUrl(storageId: 'public', path: path) (public storage only)
  • session.storage.temporaryDownloadUrl(storageId: 'private', path: path) (time-limited access to private files)
  • session.storage.retrieveFile(storageId: 'public', path: path)

Storage backends

  • Database (default): public and private storages. Fine for dev.
  • Google Cloud Storage: Add serverpod_cloud_storage_gcp, set HMAC keys in passwords.yaml or env. Register: pod.addCloudStorage(GoogleCloudStorage(...)).
  • AWS S3: Add serverpod_cloud_storage_s3, set AWS keys. Register: pod.addCloudStorage(S3CloudStorage(...)).
  • S3-compatible/R2: Use the matching integration package when targeting compatible providers.

Use storageId: 'public' or 'private' when replacing defaults.

Comments

Markdown supported