serverpod-file-uploads

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Serverpod File Uploads

Serverpod 文件上传

Flow: server issues upload description → client uploads → server verifies. Default storage is the database; use S3, GCP, R2, or compatible object storage for production.
流程:服务器生成上传描述 → 客户端上传 → 服务器验证。默认存储为数据库;生产环境建议使用 S3、GCP、R2 或兼容的对象存储。

Server: create upload description

服务端:生成上传描述

dart
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.
dart
Future<String> getUploadDescription(Session session, String path) async {
  return await session.storage.createUploadDescription(
    storageId: 'public',
    path: path,
  );
}
务必对请求进行授权,并从可信的服务端状态(用户ID、租户ID、对象ID)生成路径。请勿接受客户端传入的任意路径。

Server: verify upload

服务端:验证上传

dart
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.
dart
Future<bool> verifyUpload(Session session, String path) async {
  return await session.storage.verifyUpload(
    storageId: 'public', path: path);
}
使用对象存储时,务必在客户端上传完成后进行验证。

Client: upload

客户端:上传文件

dart
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.
dart
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');
大文件请使用
Stream
。路径规则:无前导斜杠、兼容对象存储、格式规范,并限定在已认证用户/租户的范围内。

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.
  • 对生成描述和验证的接口均要求身份认证/授权。
  • 在生成描述前,验证或确定文件的内容类型、大小和扩展名。
  • 绝不允许客户端选择跨租户的路径或存储ID。
  • verifyUpload
    成功后,将元数据存储到数据库中。

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)
  • session.storage.fileExists(storageId: 'public', path: path)
  • session.storage.publicDownloadUrl(storageId: 'public', path: path)
    (仅适用于公共存储)
  • session.storage.temporaryDownloadUrl(storageId: 'private', path: path)
    (私有文件的限时访问链接)
  • 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.
  • 数据库(默认): 包含
    public
    private
    存储。适合开发环境。
  • Google Cloud Storage: 添加
    serverpod_cloud_storage_gcp
    依赖,在
    passwords.yaml
    或环境变量中设置HMAC密钥。注册方式:
    pod.addCloudStorage(GoogleCloudStorage(...))
  • AWS S3: 添加
    serverpod_cloud_storage_s3
    依赖,设置AWS密钥。注册方式:
    pod.addCloudStorage(S3CloudStorage(...))
  • 兼容S3的存储/R2: 针对兼容的服务商,使用对应的集成包。
替换默认存储时,使用
storageId: 'public'
'private'