PG 云存储
CloudBase JS SDK v3 PG 模式提供基于 PostgreSQL 原生 Bucket 的云存储能力。通过 app.storage.from(bucketId) 获取指定 Bucket 的对象操作客户端,所有路径参数均为 Bucket 内对象名,不要传 cloud:// fileID。
PG 模式与传统模式 API 的关键差异:
| 维度 | PG 模式 | 传统模式 |
|---|---|---|
| 入口 | app.storage.from("bucketId") | app.storage.from() |
| 路径参数 | Bucket 内对象名,如 user-123/avatar.png | cloud:// fileID |
| 权限模型 | PostgreSQL RLS Policy | 内置权限 + JSON 安全规则 |
| Bucket 管理 | 支持 createBucket / listBuckets / updateBucket / deleteBucket | 不支持 |
| 文件列表 | 支持 list() | 不支持 |
| 覆盖默认值 | upsert 默认 false | upsert 默认 true |
| 跨 Bucket 操作 | move() / copy() 支持 destinationBucket | 不支持 |
| 图片转换 | 不支持 | download() / 签名 URL 支持 TransformOptions |
| 流式下载 | download().asStream() | 不支持 |
详见:API 参考(传统模式)
快速开始
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbase.init({ env: "your-env-id" });
const bucket = app.storage.from("avatars");
const { data, error } = await bucket.upload("user-123/avatar.png", file, {
contentType: "image/png",
upsert: true,
});
if (error) throw error;
const { data: blob } = await bucket.download("user-123/avatar.png");
const { data: signed } = await bucket.createSignedUrl("user-123/avatar.png", 3600);
await bucket.remove(["user-123/avatar.png"]);
API 方法
Bucket 客户端
- from() - 选择 Bucket,返回对象操作客户端
- throwOnError() - 错误时抛出异常
文件操作
- upload() - 上传文件
- update() - 更新文件
- download() - 下载文件
- remove() - 删除文件
- move() - 移动文件
- copy() - 复制文件
- list() - 列出 Bucket 中的对象
URL 管理
- createSignedUrl() - 创建签名 URL
- createSignedUrls() - 批量创建签名 URL
- getPublicUrl() - 获取公开 URL
- createSignedUploadUrl() - 创建上传签名 URL
文件信息
Bucket 管理
- Bucket 管理 - 创建、查询、更新、删除 Bucket
from
from(bucketId: string): PostgresNativeStorageFileApi
type PostgresNativeStorageFileApi = StorageFileApi;
参数
PG Bucket ID,对应 `storage.buckets.id`。
返回
PG 原生 Bucket 对象操作客户端。
示例
const bucket = app.storage.from("avatars");
throwOnError
throwOnError(): this
参数
无参数
返回
当前客户端实例,支持链式调用。
示例
const bucket = app.storage.from("avatars").throwOnError();
await bucket.upload("user-123/avatar.png", file);
upload
上传文件到云存储。
upload(
path: string,
fileBody: FileBody,
fileOptions?: UploadOptions
): Promise<Result<UploadResult>>
type FileBody = File | Blob | ArrayBuffer | ArrayBufferView | FormData | ReadableStream<Uint8Array> | string;
type Result<T> = { data: T; error: null } | { data: null; error: StorageError };
interface UploadOptions {
cacheControl?: string;
contentType?: string;
metadata?: Record<string, any>;
upsert?: boolean; // 默认 false
}
interface UploadResult {
id: string;
path: string;
fullPath: string; // bucketId/objectName
}
参数
Bucket 内对象名,如 `user-123/avatar.png`。不要传 `cloud://` fileID。
文件内容。
上传选项。默认不覆盖同名对象;覆盖需传 `upsert: true`。
返回
返回数据
错误信息。
示例
const { data, error } = await app.storage.from("avatars").upload("user-123/avatar.png", file, {
contentType: "image/png",
upsert: true,
metadata: { usage: "avatar" },
});
if (error) throw error;
console.log(data.fullPath);
update
更新已存在的文件。
update(path: string, fileBody: FileBody, fileOptions?: UploadOptions): Promise<Result<UploadResult>>
interface UploadOptions {
cacheControl?: string;
contentType?: string;
metadata?: Record<string, any>;
}
参数
Bucket 内对象名。
新的文件内容。
上传选项。
返回
更新结果。
错误信息。
示例
await app.storage.from("avatars").update("user-123/avatar.png", newFile, {
contentType: "image/png",
});
download
下载文件并返回内容。
download(
path: string,
options?: DownloadOptions,
parameters?: FetchParameters
): DownloadBuilder
interface DownloadOptions {
download?: string | boolean;
cacheNonce?: string;
}
interface FetchParameters {
signal?: AbortSignal;
cache?: RequestCache;
}
参数
Bucket 内对象名。
下载选项。
请求控制参数。
返回
默认 await 返回 Blob;调用 `.asStream()` 返回 ReadableStream。
错误信息。
示例
const { data: blob } = await app.storage.from("avatars").download("user-123/avatar.png");
const { data: stream } = await app.storage
.from("videos")
.download("demo.mp4")
.asStream();
remove
删除一个或多个文件。
remove(paths: string[]): Promise<Result<FullObject[]>>
interface FullObject {
name: string;
bucket_id: string;
owner_id?: string | null;
metadata?: Record<string, any>;
}
参数
Bucket 内对象名数组。
返回
删除成功的对象信息。
错误信息。
示例
await app.storage.from("avatars").remove(["user-123/avatar.png"]);
move
移动文件到新位置。
move(fromPath: string, toPath: string, options?: DestinationOptions): Promise<Result<{ message: string }>>
interface DestinationOptions {
destinationBucket?: string;
upsert?: boolean;
}
参数
源对象名。
目标对象名。
目标 Bucket 等选项。
返回
返回数据
错误信息。
示例
await app.storage.from("avatars").move("user-123/avatar.png", "user-123/archive/avatar.png");
copy
复制文件到新位置。
copy(fromPath: string, toPath: string, options?: DestinationOptions): Promise<Result<{ path: string }>>
interface DestinationOptions {
destinationBucket?: string;
upsert?: boolean;
copyMetadata?: boolean;
metadata?: Record<string, any>;
}
参数
源对象名。
目标对象名。
跨 Bucket、覆盖和元数据选项。
返回
返回数据
错误信息。
示例
await app.storage.from("avatars").copy("user-123/avatar.png", "user-123/avatar-copy.png", {
upsert: true,
copyMetadata: true,
});
createSignedUrl
创建文件临时访问链接。
createSignedUrl(path: string, expiresIn: number, options?: SignedUrlOptions): Promise<Result<SignedUrlResult>>
interface SignedUrlOptions {
download?: string | boolean;
cacheNonce?: string;
}
interface SignedUrlResult {
fullSignedURL: string;
}
参数
Bucket 内对象名。
有效期,单位秒。
签名 URL 选项。
返回
返回数据
错误信息。
示例
const { data } = await app.storage.from("avatars").createSignedUrl("user-123/avatar.png", 3600, {
download: "avatar.png",
});
createSignedUrls
批量创建临时访问链接。
createSignedUrls(paths: string[], expiresIn: number, options?: SignedUrlOptions): Promise<Result<SignedUrlsResultItem[]>>
interface SignedUrlsResultItem {
path: string;
fullSignedURL: string | null;
error: string | null;
}
参数
Bucket 内对象名数组。
有效期,单位秒。
签名 URL 选项。
返回
批量签名结果。
错误信息。
示例
await app.storage.from("avatars").createSignedUrls(["user-123/avatar.png"], 3600);
getPublicUrl
获取公开访问 URL。
getPublicUrl(path: string, options?: PublicUrlOptions): { data: { publicUrl: string } }
interface PublicUrlOptions {
download?: string | boolean;
cacheNonce?: string;
}
参数
Bucket 内对象名。
公开 URL 选项。
返回
返回数据
示例
const { data } = app.storage.from("public-assets").getPublicUrl("logos/cloudbase.png");
info
获取文件信息。
info(path: string): Promise<Result<ObjectInfo>>
interface ObjectInfo {
id: string;
name: string;
bucketId: string;
size?: number | null;
contentType?: string | null;
metadata?: Record<string, any>;
createdAt?: string | null;
}
参数
Bucket 内对象名。
返回
对象元信息。
错误信息。
示例
await app.storage.from("avatars").info("user-123/avatar.png");
exists
检查文件是否存在。
exists(path: string): Promise<Result<boolean>>
参数
Bucket 内对象名。
返回
是否存在。
错误信息。
示例
await app.storage.from("avatars").exists("user-123/avatar.png");
createSignedUploadUrl
创建上传签名 URL。
createSignedUploadUrl(path: string, options?: { upsert?: boolean }): Promise<Result<CreateSignedUploadUrlResult>>
interface CreateSignedUploadUrlResult {
fullSignedURL: string;
token: string;
path: string;
}
参数
Bucket 内对象名。
是否允许覆盖。
返回
签名上传 URL 与 token。
错误信息。
示例
const bucket = app.storage.from("avatars");
const { data: signed } = await bucket.createSignedUploadUrl("user-123/avatar.png", { upsert: true });
await bucket.uploadToSignedUrl("user-123/avatar.png", signed.token, file);
list
列出 Bucket 中的对象。
list(path?: string, options?: ListOptions, parameters?: FetchParameters): Promise<Result<ListObjectsResponse>>
interface ListOptions {
limit?: number;
cursor?: string;
withDelimiter?: boolean;
sortBy?: { column?: "name" | "created_at" | "updated_at"; order?: "asc" | "desc" };
}
参数
路径前缀,不传表示 Bucket 根目录。
列表选项。
返回
包含 folders、objects、hasNext、nextCursor。
错误信息。
示例
const { data } = await app.storage.from("avatars").list("user-123", {
limit: 20,
withDelimiter: true,
});
Bucket 管理
以下 API 直接挂在 app.storage 上,仅 PG 环境可用:
listBuckets(options?: ListBucketOptions): Promise<Result<Bucket[]>>
getBucket(bucketId: string): Promise<Result<Bucket>>
createBucket(bucketId: string, options?: CreateBucketOptions): Promise<Result<{ name: string }>>
updateBucket(bucketId: string, options: UpdateBucketOptions): Promise<Result<{ message: string }>>
deleteBucket(bucketId: string): Promise<Result<{ message: string }>>
interface CreateBucketOptions {
public?: boolean;
type?: "STANDARD";
fileSizeLimit?: number | string | null;
allowedMimeTypes?: string[] | null;
}
参数
Bucket ID。
Bucket 配置。
返回
Bucket 操作结果。
示例
await app.storage.createBucket("avatars", {
public: false,
type: "STANDARD",
fileSizeLimit: "100MB",
allowedMimeTypes: ["image/png", "image/jpeg"],
});
const { data: buckets } = await app.storage.listBuckets({ limit: 20, offset: 0 });
最佳实践
1. 错误处理
const { data, error } = await app.storage.from("avatars").upload("user-123/avatar.png", file);
if (error) {
console.error("操作失败:", error.message);
return;
}
2. 文件路径规范
- 先通过
from(bucketId)选择 Bucket,之后所有路径均为 Bucket 内对象名。 - 不要传
cloud://fileID。 - 路径不要以
/开头,不要包含连续/。
常见问题
1. PG 模式为什么不能传 cloud:// fileID?
PG 原生对象 API 已经通过 from(bucketId) 指定 Bucket,方法入参中的 path 表示 Bucket 内对象名,因此不需要也不应该传 cloud:// fileID。