跳到主要内容

访问与下载文件

本文介绍 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 是否真的可访问,取决于:

  1. Bucket 是否按公开资源配置;
  2. storage.objects 上是否有允许公开读取的 SELECT Policy;
  3. 对象是否存在。

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() 返回 403SELECT 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 策略。