授权下载的核心不是生成一个 URL,而是让下载动作仍然受到业务权限、有效期和日志体系控制。
当终端用户、内部后台、第三方系统或 AI 作业需要在短时间内拿到可用下载入口,但又不应直接暴露长期凭证时,授权下载通常是更稳妥的方案。
如果文件涉及权限校验、组织隔离、有效期控制或审计要求,就不应把长期可访问的公共链接直接交给客户端,而应由后端按需签发短期下载地址。
POST /api/storage/presign-download
{
"objectKey": "projects/proj_xxx/reports/2026/06/result.pdf",
"resourceType": "project-report"
}{
"success": true,
"bucket": "media-assets",
"objectKey": "projects/proj_xxx/reports/2026/06/result.pdf",
"downloadUrl": "https://your-download-url",
"expiresIn": 300,
"requestId": "req_xxx"
}前端只提交 objectKey 或业务主键,不自行拼接底层下载链接。真正的权限判断由业务后端完成。
POST /api/storage/presign-download
{
"objectKey": "projects/proj_xxx/reports/2026/06/result.pdf",
"resourceType": "project-report"
}后端确认当前用户、组织或任务是否有权读取该文件,再生成带有效期的 downloadUrl,同时记录 requestId 以便审计和排查。
{
"success": true,
"bucket": "media-assets",
"objectKey": "projects/proj_xxx/reports/2026/06/result.pdf",
"downloadUrl": "https://your-download-url",
"expiresIn": 300,
"requestId": "req_xxx"
}客户端下载时只消费短期地址。若链接过期或权限变化,重新向业务后端申请,而不是缓存旧链接长期复用。
async function downloadFile(objectKey: string) {
const response = await fetch('/api/storage/presign-download', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ objectKey }),
});
const { downloadUrl } = await response.json();
window.location.href = downloadUrl;
}下载授权同样建议由业务后端签发,而不是把对象路径和长期权限直接交给客户端。
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const client = new S3Client({
region: 'auto',
endpoint: process.env.SURUN_S3_ENDPOINT,
credentials: {
accessKeyId: process.env.SURUN_ACCESS_KEY_ID!,
secretAccessKey: process.env.SURUN_SECRET_ACCESS_KEY!,
},
});
export async function createDownloadAuthorization(params: {
objectKey: string;
currentUserId: string;
}) {
// 这里先做业务权限判断,例如确认当前用户是否能读取该对象
const command = new GetObjectCommand({
Bucket: 'media-assets',
Key: params.objectKey,
});
const downloadUrl = await getSignedUrl(client, command, { expiresIn: 300 });
return {
bucket: 'media-assets',
objectKey: params.objectKey,
downloadUrl,
expiresIn: 300,
};
}前端只负责向业务后端申请下载授权,再跳转到短时有效的 downloadUrl。
async function downloadFile(objectKey: string) {
const response = await fetch('/api/storage/presign-download', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ objectKey }),
});
const { downloadUrl } = await response.json();
window.location.href = downloadUrl;
}优先检查前后端时间是否有偏差、expiresIn 是否设置过短,或者用户拿到链接后是否隔了很久才开始下载。
优先确认 objectKey 是否就是用户真正有权限访问的那个文件,以及下载授权接口里是否有业务权限收口逻辑。
建议在签发下载地址时就记录 requestId、用户标识和 objectKey,不要把审计放到浏览器跳转之后再猜测。
建议先根据组织、时间范围和报表类型定位对象,再签发短时下载地址。这样后续做对账、过期清理和审计都更明确。
建议把 objectKey 与业务记录绑定,不要让前端直接输入任意路径。用户看到的是文件记录,而不是底层文件路径。
如果模型推理、训练输出或知识库中间产物需要回读,建议按 jobId 或 taskId 管理目录,并在签发下载前再次校验任务归属。
因为下载本身就是权限行为。谁能下载、能下载多久、下载什么文件,都应由业务系统判断。
通常几分钟级别就够了。有效期越短,泄露后的风险越低。
文档中心帮助你完成接入,客户服务页帮助你了解采购、支持与服务信息。