这篇文档主要帮助团队把仓库里已有的 `/api/storage/presign-upload` 和 `/api/storage/presign-download` 跑起来,在本地完成一轮最小上传下载验证。
接收 fileName、contentType、resourceType,返回 uploadUrl、objectKey、bucket、expiresIn 和 requestId。
接收 objectKey、fileName、contentType、size 等字段,确认对象已存在并返回统一 asset 结构。
接收 objectKey,校验当前用户只能访问自己的示例目录,再返回 downloadUrl、bucket、expiresIn 和 requestId。
这一步只影响本地示例 route 的可用性,不会改动现有业务逻辑。补充存储连接信息后,重启开发服务器即可。
SURUN_S3_ENDPOINT=https://your-s3-endpoint SURUN_S3_REGION=auto SURUN_ACCESS_KEY_ID=your-access-key SURUN_SECRET_ACCESS_KEY=your-secret-key SURUN_DEFAULT_BUCKET=media-assets
已接入前端登录时,可直接从当前 session 里读取 access_token;如在 Postman 或 curl 里验证,也需要把同一令牌放进 Authorization 头。
const {
data: { session },
} = await supabase.auth.getSession();
const accessToken = session?.access_token;
if (!accessToken) {
throw new Error('当前没有可用登录态');
}这组示例 route 不会读取浏览器里的配置,而是直接在服务端读取 SURUN_* 变量。只要缺少必要项,接口就会返回 demo_storage_unavailable。
示例 route 会从 Authorization 头里取 Bearer Token,再解析当前用户。没有登录态时,请先确认本地登录流程和 access_token 获取方式。
正确顺序是先 POST `/api/storage/presign-upload`,拿到 uploadUrl 与 objectKey,再对 uploadUrl 发 PUT。不要跳过签名阶段直接拼 URL。
现在仓库里已经有 `/api/storage/confirm-upload`。建议上传成功后立刻调用它,确认对象存在、记录 requestId,并把统一的 asset 结构返回给前端或业务层。
确认入库通过后,再用同一个 objectKey 去调用 `/api/storage/presign-download`。下载接口不会帮你猜路径,路径必须与上传返回值一致。
curl -X POST http://localhost:3000/api/storage/presign-upload \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
-d '{
"fileName": "demo-cover.png",
"contentType": "image/png",
"resourceType": "project-cover"
}'{
"success": true,
"bucket": "media-assets",
"objectKey": "docs-demo/<user-id>/project-cover/2026/06/abc123-demo-cover.png",
"uploadUrl": "https://your-upload-url",
"expiresIn": 600,
"requestId": "req_xxx"
}curl -X PUT "<UPLOAD_URL>" \ -H "Content-Type: image/png" \ --data-binary "@./demo-cover.png"
const response = await fetch('/api/storage/presign-upload', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
fileName: file.name,
contentType: file.type,
resourceType: 'project-cover',
}),
});
const result = await response.json();当前示例下载接口不会替你查业务主表,它只认 `objectKey` 和当前登录用户。因此最稳的做法是直接使用上传接口返回的原始对象路径。
curl -X POST http://localhost:3000/api/storage/presign-download \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
-d '{
"objectKey": "docs-demo/<user-id>/project-cover/2026/06/abc123-demo-cover.png"
}'这一步会让服务端重新确认对象确实已经存在于当前示例目录下,并返回统一的 `asset` 结构。后续如需接数据库、项目素材表或任务记录,可以直接以这一步为基础继续扩展。
curl -X POST http://localhost:3000/api/storage/confirm-upload \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
-d '{
"objectKey": "docs-demo/<user-id>/project-cover/2026/06/abc123-demo-cover.png",
"fileName": "demo-cover.png",
"contentType": "image/png",
"size": 248731,
"resourceType": "project-cover",
"projectId": "proj_xxx"
}'说明服务端缺少必须的 SURUN_* 环境变量,或者变量值为空。先检查本地 `.env.local` 是否真正被开发服务器读取。
因为当前 objectKey 不在 `docs-demo/{userId}/` 目录下。这个限制是故意做的,用来确保示例接口不会跨用户目录签发下载。
如果尚未调用 `/api/storage/confirm-upload`,它仍然只是一条已上传对象;真正业务里通常要等确认入库成功后,页面才把它当成正式资源展示。
文档中心帮助你完成接入,客户服务页帮助你了解采购、支持与服务信息。