访问与下载文件
本文介绍 PG 模式云存储中文件的访问方式,包括直接下载、签名下载链接、批量签名链接和公开 URL。
访问方式对比
| 方式 | 适用场景 | 权限要求 | 特点 |
|---|---|---|---|
download() | 当前用户直接读取文件内容 | 需要 SELECT Policy 放行 | 返回 Blob 或流 |
createSignedUrl() | 私有文件临时分享 | 创建签名链接时需要 SELECT 权限 | 链接有有效期 |
createSignedUrls() | 批量生成临时下载链接 | 每个对象都需要 SELECT 权限 | 适合列表页批量展示 |
getPublicUrl() | 公开资源访问 | Bucket 与 RLS 允许公开读 | 只拼接 URL,不发起请求 |
| HTTP API 下载 | 服务端或跨语言访问 | Token 或签名链接 | 适合后端集成 |
直接下载
使用 download() 下载对象,默认返回 Blob:
const bucket = app.storage.from('private-files');
const { data: blob, error } = await bucket.download('user-123/resume.pdf');
if (error) {
throw error;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'resume.pdf';
a.click();
URL.revokeObjectURL(url);
如果运行时支持流式读取,可以使用 .asStream():
const { data: stream, error } = await bucket
.download('videos/demo.mp4')
.asStream();
if (error) {
throw error;
}
签名下载链接
对于私有文件,推荐通过 createSignedUrl() 生成限时访问链接:
const { data, error } = await bucket.createSignedUrl('user-123/resume.pdf', 600, {
download: 'resume.pdf',
});
if (error) {
throw error;
}
console.log(data.fullSignedURL);
第二个参数是有效期,单位为秒。上例中链接有效期为 600 秒。
签名链接适合临时分享,不适合长期公开资源。长期公开资源建议使用公开 Bucket +
getPublicUrl()。
批量签名下载链接
列表页经常需要一次性为多张图片或多个附件生成临时链接:
const { data, error } = await bucket.createSignedUrls([
'user-123/a.png',
'user-123/b.png',
], 600);
if (error) {
throw error;
}
console.log(data);
每个对象仍会受 SELECT Policy 控制。没有读取权限的对象不会因为批量签名而绕过权限。
公开 URL
如果文件属于公开资源,可使用 getPublicUrl() 生成公开访问地址:
const { data } = app.storage
.from('public-assets')
.getPublicUrl('logos/cloudbase.png');
console.log(data.publicUrl);
getPublicUrl() 只负责生成 URL,不会请求服务端。URL 是否真的可访问,取决于:
- Bucket 是否按公开资源配置;
storage.objects上是否有允许公开读取的SELECTPolicy;- 对象是否存在。
Public / Private 场景建议
| 场景 | 推荐方式 | 说明 |
|---|---|---|
| Logo、公开 Banner、文章公开图片 | getPublicUrl() | 适合长期公开和缓存 |
| 用户私密附件 | download() | 当前登录用户读取自己的文件 |
| 临时分享私有文件 | createSignedUrl() | 给外部用户短时间访问 |
| 私有列表页缩略图 | createSignedUrls() | 批量生成短期链接 |
| 服务端转发下载 | HTTP API | 后端统一鉴权、审计、限速 |
CDN 加速
如果公开资源需要更高的访问性能和缓存命中率,可开启 CDN 加速。PG 模式云存储的 CDN 能力已独立说明,参见 CDN 加速与缓存。
RLS 与访问操作
读取、下载、签名链接和列表都可能命中 SELECT,但业务上往往需要区分:
| SDK 操作 | DML | 常见权限目标 |
|---|---|---|
download() | SELECT | 允许读取文件内容 |
createSignedUrl() | SELECT | 允许生成临时访问链接 |
createSignedUrls() | SELECT | 允许批量生成临时访问链接 |
getPublicUrl() | 不一定发起请求 | URL 是否可访问由服务端读取策略决定 |
list() | SELECT | 允许列出目录或文件列表 |
info() / exists() | SELECT | 允许读取对象元信息 |
如果你希望「允许用户访问已知路径,但不允许列目录」,可结合 storage.operation()、storage.allow_only_operation() 或 storage.allow_any_operation() 写更细粒度策略。详见 权限管理:与对象路径配合的辅助函数。
缓存与覆盖
公开资源通常会被浏览器或 CDN 缓存。若你覆盖同一路径文件,用户可能短时间内仍访问到旧内容。详细建议见 CDN 加速与缓存:覆盖文件与 CDN 缓存。
排障速查
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
download() 返回 403 | SELECT Policy 不放行 | 检查对象路径、bucket_id、当前 auth.uid() |
| 签名 URL 生成失败 | 当前用户无读取权限 | 用 SQL 查询对象元数据并复核 RLS |
| 公开 URL 访问失败 | 只有 URL,没有公开读 Policy | 为公开 Bucket 补充 SELECT TO anon 策略 |
| 访问到旧文件 | 缓存尚未刷新 | 使用新路径或更新 URL 版本参数 |
AI 友好提示
让 AI 生成下载或分享逻辑时,建议明确以下信息:
文件是否公开:否
访问者:文件 owner 或团队成员
访问方式:生成 10 分钟签名下载链接
是否允许列目录:不允许,只允许访问指定对象
路径模板:<uid>/<filename>
这样 AI 更容易选择 createSignedUrl() 而不是错误地生成公开 URL,也更容易写出不会泄露目录列表的 RLS 策略。