@data-loom/storage-js
v0.4.13
Published
Dataloom service, modified from supabase/storage-js
Readme
@data-loom/storage-js
Dataloom 存储服务 JavaScript SDK,基于 Supabase Storage 修改而来,提供了强大的文件存储和管理功能。
功能特性
- 📁 文件上传和下载 - 支持多种文件格式的上传和下载
- 🔗 签名URL - 创建具有时效性的安全文件访问链接
- 🗑️ 文件管理 - 删除、列表等文件操作
- 🌐 URL上传 - 从公共URL下载文件并上传到存储桶
- 📊 批量操作 - 支持批量创建签名URL等批量操作
- 🔍 文件搜索 - 支持文件搜索和分页
- 🛡️ 错误处理 - 完善的错误处理机制
安装
npm install @data-loom/storage-js快速开始
默认推荐使用挂载在 @data-loom/js 中的 storage 接口。
import { createClient } from '@data-loom/js';
const dataloom = createClient(url, key, workspace, {
global: {
brandName: 'your_brand_name',
appId: 'your_app_id',
enableDataloomLog: true,
requestRateLimit: 10,
onError: (error) => {
}
},
});
const { data, error } = await dataloom.storage.from('bucket_id').download('file_path');或者可以独立使用 storage-js 包。
import { StorageClient } from '@data-loom/storage-js'
// 独立初始化存储客户端
const storage = new StorageClient(
storageUrl,
customHeaders,
customFetch,
{
enableLogger: true,
appId: 'your-app-id',
onRequestError: (error) => console.error('请求错误:', error),
},
);
// 上传文件
const { data, error } = await storage.upload('folder/image.png', file);
if (error) {
console.error('上传失败:', error);
} else {
console.log('上传成功:', data);
}API 接口文档
构造函数
constructor(
url: string, // 存储服务URL
headers: { [key: string]: string } = {}, // 请求头
bucketId?: string, // 存储桶ID
appId?: string, // 应用ID
fetch?: Fetch, // 自定义fetch函数
loggerEnabled?: boolean, // 是否启用日志
onRequestError?: (error: OnRequestErrorType) => void // 请求错误回调
)文件上传
upload(path, fileBody, fileOptions?) - 重载1
上传文件到指定的存储桶路径。
入参:
function upload(
path: string, // 文件路径,格式为 `folder/subfolder/filename.png`
fileBody: FileBody, // 文件内容
fileOptions?: FileOptions // 上传选项
): Promise<UploadResult>出参:
type UploadResult =
| { data: UploadFileData; error: null }
| { data: null; error: StorageError }示例:
const { data, error } = await storage.upload('avatars/user-123.jpg', file, {
cacheControl: 3600,
contentType: 'image/jpeg',
upsert: false
});upload(fileBody, fileOptions?) - 重载2
使用 FileOptionsV2 上传文件,路径通过 options.filePath 指定。
入参:
function upload(
fileBody: FileBody, // 文件内容
fileOptions?: FileOptionsV2 // 上传选项(包含 filePath)
): Promise<UploadResult>出参:
type UploadResult =
| { data: UploadFileData; error: null }
| { data: null; error: StorageError }示例:
const { data, error } = await storage.upload(file, {
filePath: 'documents/report.pdf',
contentType: 'application/pdf',
contentDisposition: 'attachment; filename="report.pdf"'
});uploadFile(fileBody, fileOptions?)
使用文件选项上传文件(推荐,与 upload 重载2 功能相同)。
入参:
function uploadFile(
fileBody: FileBody, // 文件内容
fileOptions?: FileOptionsV2 // 上传选项
): Promise<UploadResult>出参:
type UploadResult =
| { data: UploadFileData; error: null }
| { data: null; error: StorageError }示例:
const { data, error } = await storage.uploadFile(file, {
filePath: 'documents/report.pdf',
cacheControl: 3600,
contentType: 'application/pdf',
contentDisposition: 'attachment; filename="report.pdf"'
});文件更新
update(path, fileBody, fileOptions?)
替换指定路径的现有文件。
入参:
function update(
path: string, // 文件路径
fileBody: FileBody, // 文件内容
fileOptions?: FileOptions // 上传选项
): Promise<UploadResult>出参:
type UploadResult =
| { data: UploadFileData; error: null }
| { data: null; error: StorageError }从URL上传文件
uploadFromUrl(url)
从公共URL上传文件到存储桶。自动透传响应头(content-type、content-disposition、cache-control)到上传请求。对于火山引擎北京区域的 TOS URL,会使用服务端复制优化性能。
入参:
function uploadFromUrl(
url: string // 公共文件URL(如 CDN 链接)
): Promise<UploadFromUrlResult>出参:
type UploadFromUrlResult =
| { data: UploadFileData; error: null }
| { data: null; error: StorageError }功能特性:
- ✅ 只允许
http://和https://协议 - ✅ 自动透传响应头到上传请求(contentType、contentDisposition、cacheControl)
- ✅ 检测并拒绝空文件
- ✅ 火山引擎北京区域 TOS URL 使用服务端复制优化
示例:
// 基本用法
const { data, error } = await storage.uploadFromUrl(
'https://cdn.example.com/images/photo.jpg'
);
if (data) {
console.log('文件上传成功:', data.download_url);
}错误处理:
const { data, error } = await storage.uploadFromUrl('https://example.com/file.pdf');
if (error) {
// 可能的错误类型:
// - 'Invalid URL provided' - URL格式无效
// - 'Only http and https protocols are supported' - 协议不支持
// - 'Failed to download file from URL: 404 Not Found' - 下载失败
// - 'Downloaded file is empty' - 下载的文件为空
console.error(error.message);
}创建签名URL
createSignedUrl(path, expiresIn, options?)
创建具有时效性的安全文件访问链接。
入参:
function createSignedUrl(
path: string, // 文件路径或 download_url
expiresIn: number, // 过期时间(秒)
options?: {
download?: string | boolean; // 是否触发下载
transform?: TransformOptions; // 图片转换选项
}
): Promise<SignedUrlResult>出参:
type SignedUrlResult =
| { data: { signedUrl: string }; error: null }
| { data: null; error: StorageError }示例:
// 创建1小时有效的签名URL
const { data, error } = await storage.createSignedUrl('documents/report.pdf', 3600);
// 创建带图片转换的签名URL
const { data, error } = await storage.createSignedUrl('images/photo.jpg', 3600, {
transform: {
width: 300,
height: 200,
resize: 'cover',
quality: 80
}
});createSignedUrls(paths, expiresIn, options?)
批量创建签名URL。
入参:
function createSignedUrls(
paths: string[], // 文件路径或 download_url 数组
expiresIn: number, // 过期时间(秒)
options?: {
download?: string | boolean;
}
): Promise<SignedUrlsResult>出参:
type SignedUrlsResult =
| {
data: Array<{
error: string | null;
path: string | null;
signedUrl: string;
}>;
error: null
}
| { data: null; error: StorageError }示例:
const { data, error } = await storage.createSignedUrls(
['file1.pdf', 'file2.pdf', 'file3.pdf'],
3600
);文件下载
download(path, options?)
从私有存储桶下载文件。
入参:
function download(
path: string, // 文件路径
options?: {
transform?: TransformOptions; // 图片转换选项
}
): Promise<DownloadResult>出参:
type DownloadResult =
| { data: Blob; error: null }
| { data: null; error: StorageError }示例:
const { data, error } = await storage.download('documents/report.pdf');
if (data) {
const url = URL.createObjectURL(data);
window.open(url);
}文件删除
remove(paths)
删除指定路径的文件。
入参:
function remove(
paths: string[] // 文件路径或 download_url 数组
): Promise<RemoveResult>出参:
type RemoveResult =
| { data: FileObject[]; error: null }
| { data: null; error: StorageError }示例:
const { data, error } = await storage.remove([
'temp/file1.txt',
'temp/file2.txt'
]);文件列表
list(path?, options?, parameters?)
列出存储桶中的文件。
入参:
function list(
path?: string, // 文件夹路径
options?: SearchOptions, // 搜索选项
parameters?: FetchParameters // 请求参数
): Promise<ListResult>出参:
type ListResult =
| { data: FileObject[]; error: null }
| { data: null; error: StorageError }示例:
// 列出根目录文件
const { data, error } = await storage.list();
// 搜索特定文件夹的文件
const { data, error } = await storage.list('documents', {
limit: 50,
offset: 0,
sortBy: {
column: 'name',
order: 'asc'
},
search: 'report'
});类型定义
FileBody
支持以下文件格式:
type FileBody =
| ArrayBuffer
| ArrayBufferView
| Blob
| Buffer
| File
| FormData
| NodeJS.ReadableStream
| ReadableStream<Uint8Array>
| URLSearchParams
| string;FileOptions
interface FileOptions {
/** 缓存控制时间(秒),设置 Cache-Control: max-age=<seconds> 头 */
cacheControl?: string | number;
/** Content-Type 头值 */
contentType?: string;
/** 是否覆盖已存在文件,默认 false */
upsert?: boolean;
/** 双工流选项 */
duplex?: string;
/** 文件元数据 */
metadata?: Record<string, any>;
/** 额外请求头 */
headers?: Record<string, string>;
}FileOptionsV2
interface FileOptionsV2 {
/** 文件上传路径 */
filePath?: string;
/** 缓存控制时间(秒) */
cacheControl?: string | number;
/** Content-Type 头值 */
contentType?: string;
/** 是否覆盖已存在文件,默认 false */
upsert?: boolean;
/** Content-Disposition 响应头值 */
contentDisposition?: string;
}UploadFileData
interface UploadFileData {
/** 文件ID */
id: string;
/** 文件路径 */
file_path: string;
/** 存储桶ID */
bucket_id: string;
/** 下载URL */
download_url: string;
}FileObject
interface FileObject {
/** 文件名 */
name: string;
/** 存储桶ID */
bucket_id: string;
/** 所有者 */
owner: string;
/** 文件ID */
id: string;
/** 更新时间 */
updated_at: string;
/** 创建时间 */
created_at: string;
/** 创建者 */
created_by: string;
/** 更新者 */
updated_by: string;
/** 最后访问时间 */
last_accessed_at?: string;
/** 元数据 */
metadata: Record<string, any>;
/** 存储桶信息 */
buckets: Bucket;
}Bucket
interface Bucket {
/** 存储桶ID */
id: string;
/** 存储桶类型 */
type?: 'STANDARD' | 'ANALYTICS';
/** 存储桶名称 */
name: string;
/** 所有者 */
owner: string;
/** 文件大小限制 */
file_size_limit?: number;
/** 允许的MIME类型 */
allowed_mime_types?: string[];
/** 创建时间 */
created_at: string;
/** 更新时间 */
updated_at: string;
/** 是否公开 */
public: boolean;
}SearchOptions
interface SearchOptions {
/** 返回文件数量,默认 100 */
limit?: number;
/** 起始位置 */
offset?: number;
/** 排序选项 */
sortBy?: SortBy;
/** 搜索字符串 */
search?: string;
}SortBy
interface SortBy {
/** 排序列名 */
column?: string;
/** 排序顺序:'asc' | 'desc' */
order?: string;
}TransformOptions
interface TransformOptions {
/** 宽度(像素) */
width?: number;
/** 高度(像素) */
height?: number;
/** 调整大小模式 */
resize?: 'cover' | 'contain' | 'fill';
/** 质量(20-100) */
quality?: number;
/** 格式 */
format?: 'origin';
}FetchParameters
interface FetchParameters {
/** AbortController 信号,用于取消请求 */
signal?: AbortSignal;
}StorageError
class StorageError extends Error {
message: string;
}OnRequestErrorType
interface OnRequestErrorType {
code: number;
details: string;
hint: string | null;
message: string;
status: number;
statusText: string;
}错误处理
所有API方法都返回包含 data 和 error 的对象。当操作成功时,error 为 null,data 包含返回数据;当操作失败时,data 为 null,error 包含错误信息。
const { data, error } = await storage.upload('test.jpg', file);
if (error) {
console.error('操作失败:', error.message);
} else {
console.log('操作成功:', data);
}高级用法
日志记录
可以通过设置 loggerEnabled 参数启用请求日志记录:
const storage = new StorageFileApi(
'https://your-storage-service.com',
{ 'Authorization': 'Bearer your-token' },
'bucket-id',
'app-id',
undefined,
true // 启用日志
);错误回调
可以设置请求错误回调函数:
const storage = new StorageFileApi(
'https://your-storage-service.com',
{ 'Authorization': 'Bearer your-token' },
'bucket-id',
'app-id',
undefined,
false,
(error) => {
console.error('请求错误:', error);
}
);自定义 fetch
可以传入自定义的 fetch 函数:
const customFetch = (url, options) => {
// 自定义 fetch 逻辑
return fetch(url, options);
};
const storage = new StorageFileApi(
'https://your-storage-service.com',
{ 'Authorization': 'Bearer your-token' },
'bucket-id',
'app-id',
customFetch
);许可证
MIT License
