src/lib/plugins/storage/s3.ts
AWS S3 存储插件,支持文件上传到 Amazon S3 或兼容 S3 协议的服务(MinIO、Wasabi 等)。
概述
该插件基于 AWS SDK for JavaScript v3,提供完整的 S3 文件上传和管理功能。
主要导出
s3StoragePlugin
存储插件实例,实现了 StoragePlugin 接口。
import { s3StoragePlugin } from "@/lib/plugins/storage/s3";
功能特性
动态加载 AWS SDK
使用动态导入避免在非 S3 模式下打包 AWS SDK:
async function getS3Client() {
const s3Module = await import(/* webpackIgnore: true */ "@aws-sdk/client-s3");
return s3Module;
}
文件上传
- 支持
File对象和Buffer - 自动生成唯一文件名
- 支持自定义文件夹路径
- 自动检测或指定 MIME 类型
文件删除
- 支持通过 key 或完整 URL 删除
- 自动从 URL 中提取 key
S3 兼容服务支持
通过 S3_ENDPOINT 环境变量支持兼容 S3 的服务:
- MinIO
- DigitalOcean Spaces
- Wasabi
- Cloudflare R2
- 其他 S3 兼容服务
环境变量
# 必需
S3_BUCKET=your-bucket-name
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=your-access-key-id
S3_SECRET_ACCESS_KEY=your-secret-access-key
# 可选(用于 S3 兼容服务)
S3_ENDPOINT=https://s3.custom-endpoint.com
API 参考
isConfigured
检查 S3 是否已正确配置:
isConfigured: () => boolean
验证所有必需的环境变量是否已设置。
upload
上传文件到 S3:
async upload(
file: File | Buffer,
options?: UploadOptions
): Promise<UploadResult>
参数:
| 参数 | 类型 | 说明 | |
|---|---|---|---|
| file | `File \ | Buffer` | 要上传的文件 |
| options?.filename | string | 自定义文件名(可选) | |
| options?.mimeType | string | MIME 类型(Buffer 时必需) | |
| options?.folder | string | 目标文件夹(默认:"uploads") |
返回值:
interface UploadResult {
url: string; // 文件访问 URL
key: string; // S3 对象 key
size: number; // 文件大小(字节)
mimeType?: string; // MIME 类型
}
示例:
// 上传文件对象
const result = await s3StoragePlugin.upload(file, {
folder: "avatars",
});
// 上传 Buffer
const result = await s3StoragePlugin.upload(buffer, {
filename: "custom-name.jpg",
mimeType: "image/jpeg",
folder: "images",
});
delete
从 S3 删除文件:
async delete(keyOrUrl: string): Promise<void>
支持两种格式:
- Key:
uploads/file-1234567890-abc123.jpg - URL:
https://s3.region.amazonaws.com/bucket/uploads/file-1234567890-abc123.jpg
示例:
// 通过 key 删除
await s3StoragePlugin.delete("uploads/file-123.jpg");
// 通过 URL 删除
await s3StoragePlugin.delete("https://s3.amazonaws.com/mybucket/uploads/file-123.jpg");
配置方式
在环境变量中启用:
ENABLED_STORAGE=s3
并配置上述所有必需的环境变量。
文件名生成
自动生成唯一文件名:
const timestamp = Date.now(); // 时间戳
const randomId = Math.random().toString(36).substring(2, 8); // 随机 ID
const key = `${folder}/file-${timestamp}-${randomId}`;
URL 构造
标准 S3
const url = `https://s3.${region}.amazonaws.com/${bucket}/${key}`;
自定义 Endpoint
const url = `${endpoint}/${bucket}/${key}`;
安装依赖
使用此插件需要安装 AWS SDK:
npm install @aws-sdk/client-s3
注意事项
- 动态导入:AWS SDK 只在实际使用时加载
- 权限配置:确保 AWS 凭证有正确的 S3 权限(PutObject, DeleteObject)
- 公开访问:默认上传的文件可能需要额外的 ACL 或 Bucket Policy 才能公开访问
- CORS 配置:前端直传时需要配置 Bucket CORS
- forcePathStyle:使用自定义 endpoint 时启用路径样式 URL