serverpod-file-uploads
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseServerpod 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 for large files. Paths: no leading slash, object-store compatible, normalized, and scoped to the authenticated user/tenant.
Streamdart
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');大文件请使用 。路径规则:无前导斜杠、兼容对象存储、格式规范,并限定在已认证用户/租户的范围内。
StreamSecurity 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 succeeds.
verifyUpload
- 对生成描述和验证的接口均要求身份认证/授权。
- 在生成描述前,验证或确定文件的内容类型、大小和扩展名。
- 绝不允许客户端选择跨租户的路径或存储ID。
- 在 成功后,将元数据存储到数据库中。
verifyUpload
Accessing stored files
访问已存储文件
session.storage.fileExists(storageId: 'public', path: path)- (public storage only)
session.storage.publicDownloadUrl(storageId: 'public', path: path) - (time-limited access to private files)
session.storage.temporaryDownloadUrl(storageId: 'private', path: path) 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): and
publicstorages. Fine for dev.private - Google Cloud Storage: Add , set HMAC keys in
serverpod_cloud_storage_gcpor env. Register:passwords.yaml.pod.addCloudStorage(GoogleCloudStorage(...)) - AWS S3: Add , set AWS keys. Register:
serverpod_cloud_storage_s3.pod.addCloudStorage(S3CloudStorage(...)) - S3-compatible/R2: Use the matching integration package when targeting compatible providers.
Use or when replacing defaults.
storageId: 'public''private'- 数据库(默认): 包含 和
public存储。适合开发环境。private - Google Cloud Storage: 添加 依赖,在
serverpod_cloud_storage_gcp或环境变量中设置HMAC密钥。注册方式:passwords.yaml。pod.addCloudStorage(GoogleCloudStorage(...)) - AWS S3: 添加 依赖,设置AWS密钥。注册方式:
serverpod_cloud_storage_s3。pod.addCloudStorage(S3CloudStorage(...)) - 兼容S3的存储/R2: 针对兼容的服务商,使用对应的集成包。
替换默认存储时,使用 或 。
storageId: 'public''private'