Utils
S3 对象存储 SDK
A flexible S3-compatible object storage SDK with automatic STS credential refresh, progress tracking, and batch upload support.
特性
- ✅ 自动缓存和刷新 STS 临时凭证
- ✅ 支持单文件和批量上传
- ✅ 上传进度回调
- ✅ 错误处理
- ✅ TypeScript 类型支持
- ✅ 灵活的配置选项
安装依赖
npm install @aws-sdk/client-s3 @aws-sdk/lib-storage dayjs快速开始
创建 SDK 实例
import { createS3SDK } from './s3';
// 定义获取 STS 凭证的函数
async function fetchSTSCredentials() {
const response = await fetch('/api/tos/session');
const data = await response.json();
return {
accessKeyId: data.result.credentials.accessKeyId,
secretAccessKey: data.result.credentials.secretAccessKey,
sessionToken: data.result.credentials.sessionToken,
expiredTime: data.result.credentials.expiredTime,
};
}
// 创建 SDK 实例
const s3SDK = createS3SDK({
endpoint: 'tos-s3-cn-guangzhou.volces.com',
bucket: 'your-bucket-name',
region: 'cn-guangzhou',
fetchCredentials: fetchSTSCredentials,
});上传文件
// 基础上传
const url = await s3SDK.upload({
file: yourFile,
});
// 带进度的上传
const url = await s3SDK.upload({
file: yourFile,
prefix: 'uploads', // 文件路径前缀
onProgress: (percent) => {
console.log(`上传进度: ${percent}%`);
},
onError: (error) => {
console.error('上传失败:', error);
},
});自定义文件路径
const url = await s3SDK.upload({
file: yourFile,
key: 'custom/path/2024-01-01/filename.jpg', // 完全自定义路径
});批量上传
const results = await s3SDK.uploadBatch(files, {
prefix: 'batch-uploads',
onBatchProgress: (completed, total) => {
console.log(`进度: ${completed}/${total}`);
},
});
// 检查结果
results.forEach(({ file, url, error }) => {
if (url) {
console.log(`✓ ${file.name} 上传成功`);
} else {
console.error(`✗ ${file.name} 上传失败:`, error);
}
});API 文档
createS3SDK(config)
创建 S3 SDK 实例。
参数:
interface S3SDKConfig {
endpoint: string; // S3 端点
bucket: string; // 存储桶名称
region: string; // 区域
fetchCredentials: () => Promise<STSCredentials>; // 获取凭证的函数
refreshBeforeExpire?: number; // 提前刷新时间(毫秒),默认 60000
}返回: S3SDK 实例
s3SDK.upload(options)
上传单个文件。
参数:
interface UploadOptions {
file: File; // 要上传的文件
key?: string; // 自定义文件路径
prefix?: string; // 路径前缀(默认: 'uploads')
onProgress?: (percent: number) => void; // 进度回调
onError?: (error: unknown) => void; // 错误回调
partSize?: number; // 分片大小(字节),默认 5MB
}返回: Promise<string | null> - 成功返回文件 URL,失败返回 null
s3SDK.uploadBatch(files, options)
批量上传文件。
参数:
files: File[] // 要上传的文件数组
options: Omit<UploadOptions, 'file'> & {
onBatchProgress?: (completed: number, total: number) => void;
}返回:
Promise<Array<{
file: File;
url: string | null;
error?: unknown;
}>>s3SDK.getClient()
获取 S3 客户端实例(通常不需要直接调用)。
返回: Promise<S3Client>
s3SDK.destroy()
销毁 SDK 实例,清理资源。
// 在应用卸载时调用
s3SDK.destroy();React 组件示例
import React, { useState } from 'react';
import { createS3SDK } from './s3';
const s3SDK = createS3SDK({
// ... 配置
});
function FileUploader() {
const [progress, setProgress] = useState(0);
const [url, setUrl] = useState<string | null>(null);
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const uploadedUrl = await s3SDK.upload({
file,
onProgress: setProgress,
onError: (error) => {
console.error('上传失败:', error);
},
});
setUrl(uploadedUrl);
};
return (
<div>
<input type="file" onChange={handleUpload} />
{progress > 0 && <progress value={progress} max={100} />}
{url && <img src={url} alt="Uploaded" />}
</div>
);
}高级用法
自定义凭证刷新策略
const s3SDK = createS3SDK({
// ...
refreshBeforeExpire: 5 * 60 * 1000, // 提前 5 分钟刷新凭证
});自定义分片大小
await s3SDK.upload({
file: largeFile,
partSize: 10 * 1024 * 1024, // 10MB 分片
});与原有代码兼容
如果你需要保持与原有代码的兼容性:
// 创建全局实例
const s3SDK = createS3SDK({ /* ... */ });
// 导出兼容函数
export async function uploadToS3({ file, key, onProgress, onError }) {
return s3SDK.upload({ file, key, onProgress, onError });
}
export async function getS3Client() {
return s3SDK.getClient();
}错误处理
const url = await s3SDK.upload({
file: yourFile,
onError: (error) => {
if (error instanceof Error) {
// 处理特定错误
if (error.message.includes('credentials')) {
console.error('凭证错误,请检查 STS 配置');
}
}
},
});
if (!url) {
// 上传失败的处理逻辑
}注意事项
- 凭证自动刷新: SDK 会在凭证过期前自动刷新,无需手动处理
- 客户端缓存: S3 客户端会被缓存以提高性能
- 资源清理: 在应用卸载时记得调用
destroy()方法 - 文件路径: 如果不指定
key,文件会保存到{prefix}/{YYYY-MM-DD}/{filename}
支持的对象存储服务
这个 SDK 兼容所有支持 S3 协议的对象存储服务:
- AWS S3
- 火山引擎 TOS
- 阿里云 OSS (S3 兼容模式)
- 腾讯云 COS (S3 兼容模式)
- MinIO
- 其他 S3 兼容服务