573 lines
14 KiB
Markdown
573 lines
14 KiB
Markdown
# YX OSS
|
||
|
||
[](https://pub.dev/packages/yx_oss)
|
||
[](https://pub.dev/documentation/yx_oss/latest/)
|
||
[](https://opensource.org/licenses/MIT)
|
||
|
||
一个专注于核心功能的阿里云 OSS (Object Storage Service) Flutter 客户端库,提供纯净的文件上传下载能力。
|
||
|
||
## 🎯 设计理念
|
||
|
||
**单一职责**:本库专注于 OSS 核心操作 - 文件上传、下载和管理。故意排除了 UI 组件、图片压缩、文件选择等功能,保持简洁性和灵活性。
|
||
|
||
**最小依赖**:仅包含 OSS 操作的必需依赖,让您可以自由选择自己的 UI 和工具库。
|
||
|
||
## ✨ 核心特性
|
||
|
||
### 认证与配置
|
||
- 🔐 **多种认证方式**:静态密钥、STS临时凭证、预签名URL
|
||
- ⚙️ **动态配置**:运行时配置更新和缓存
|
||
- 🔌 **可插拔提供者**:灵活的认证和配置提供者架构
|
||
|
||
### 上传与下载
|
||
- 📤 **断点续传**:支持大文件的断点续传,本地存储断点信息
|
||
- 🧩 **分片上传**:大文件自动分片处理,支持并发上传
|
||
- 📊 **进度监控**:实时上传下载进度跟踪
|
||
- ⚡ **预签名URL**:支持客户端直接上传,服务端控制权限
|
||
|
||
### 可靠性与错误处理
|
||
- 🔄 **重试机制**:指数退避重试失败操作
|
||
- 🛡️ **类型安全错误处理**:完整的错误类型和处理
|
||
- ❌ **取消支持**:可取消正在进行的操作
|
||
- 📝 **统一日志**:可配置的日志系统,支持自定义处理器
|
||
|
||
### 架构特点
|
||
- 🎯 **零耦合**:不依赖特定项目架构
|
||
- 📱 **跨平台**:支持 iOS、Android、Web、Desktop
|
||
- 🏗️ **清洁架构**:依赖注入和关注点分离
|
||
- 🔧 **项目集成**:提供现成的项目集成适配器
|
||
|
||
## 🚀 快速开始
|
||
|
||
### 安装
|
||
|
||
在你的 `pubspec.yaml` 文件中添加依赖:
|
||
|
||
```yaml
|
||
dependencies:
|
||
yx_oss: ^1.0.0
|
||
```
|
||
|
||
然后运行:
|
||
|
||
```bash
|
||
flutter pub get
|
||
```
|
||
|
||
### 基础用法
|
||
|
||
```dart
|
||
import 'package:yx_oss/yx_oss.dart';
|
||
|
||
// 1. 创建认证提供者
|
||
final authProvider = StaticAuthProvider(
|
||
accessKeyId: 'your_access_key_id',
|
||
accessKeySecret: 'your_access_key_secret',
|
||
);
|
||
|
||
// 2. 创建配置提供者
|
||
final configProvider = StaticConfigProvider(
|
||
endpoint: 'oss-cn-hangzhou.aliyuncs.com',
|
||
bucketName: 'your-bucket-name',
|
||
directory: 'uploads',
|
||
);
|
||
|
||
// 3. 创建客户端配置
|
||
final config = YxOSSConfig(
|
||
authProvider: authProvider,
|
||
configProvider: configProvider,
|
||
logConfig: LogConfig(
|
||
enabled: true,
|
||
level: LogLevel.info,
|
||
logError: true,
|
||
),
|
||
);
|
||
|
||
// 4. 创建OSS客户端
|
||
final client = YxOSSClient(config);
|
||
|
||
// 5. 初始化客户端
|
||
await client.initialize();
|
||
|
||
// 6. 上传文件
|
||
final fileData = Uint8List.fromList('Hello, World!'.codeUnits);
|
||
final result = await client.uploadBytes(
|
||
fileData,
|
||
'my-file.txt',
|
||
options: UploadOptions(
|
||
callbacks: UploadCallbacks(
|
||
onProgress: (sent, total) {
|
||
print('进度: ${(sent / total * 100).toStringAsFixed(1)}%');
|
||
},
|
||
onSuccess: (result) {
|
||
print('上传成功: ${result.url}');
|
||
},
|
||
),
|
||
),
|
||
);
|
||
|
||
// 7. 释放资源
|
||
client.dispose();
|
||
```
|
||
|
||
## 📖 详细文档
|
||
|
||
### 认证方式
|
||
|
||
#### 1. 静态认证 (Static Authentication)
|
||
|
||
适用于开发测试环境或简单应用场景:
|
||
|
||
```dart
|
||
final authProvider = StaticAuthProvider(
|
||
accessKeyId: 'your_access_key_id',
|
||
accessKeySecret: 'your_access_key_secret',
|
||
);
|
||
```
|
||
|
||
#### 2. STS临时凭证 (STS Authentication)
|
||
|
||
适用于生产环境,提供更安全的权限控制:
|
||
|
||
```dart
|
||
// 从服务器获取STS凭证的函数
|
||
Future<STSCredentials> getSTSCredentials() async {
|
||
// 调用你的后端API获取STS凭证
|
||
final response = await http.get('/api/sts-credentials');
|
||
return STSCredentials.fromJson(response.data);
|
||
}
|
||
|
||
final authProvider = STSAuthProvider(
|
||
accessKeyId: stsCredentials.accessKeyId,
|
||
accessKeySecret: stsCredentials.accessKeySecret,
|
||
securityToken: stsCredentials.securityToken,
|
||
expiration: stsCredentials.expiration,
|
||
credentialsGetter: getSTSCredentials, // 自动刷新过期凭证
|
||
);
|
||
```
|
||
|
||
#### 3. 项目集成认证 (Project Integration)
|
||
|
||
适用于现有项目集成,从后端API获取配置:
|
||
|
||
```dart
|
||
// 使用项目集成适配器
|
||
final manager = ProjectOSSManager(myApiImpl);
|
||
await manager.initialize();
|
||
|
||
// 直接使用,自动处理认证和配置
|
||
final fileUrl = await manager.uploadFile(
|
||
filePath,
|
||
onProgress: (sent, total) => print('进度: $sent/$total'),
|
||
type: 1, // 文件类型
|
||
);
|
||
```
|
||
|
||
### 配置管理
|
||
|
||
#### 1. 静态配置 (Static Configuration)
|
||
|
||
```dart
|
||
final configProvider = StaticConfigProvider(
|
||
endpoint: 'oss-cn-hangzhou.aliyuncs.com',
|
||
bucketName: 'your-bucket-name',
|
||
directory: 'uploads',
|
||
domain: 'https://your-custom-domain.com', // 可选
|
||
);
|
||
```
|
||
|
||
#### 2. 动态配置 (Dynamic Configuration)
|
||
|
||
支持从服务器动态获取配置,适用于多环境部署:
|
||
|
||
```dart
|
||
final configProvider = DynamicConfigProvider(
|
||
configGetter: () async {
|
||
final response = await http.get('/api/oss-config');
|
||
return OSSConfig.fromJson(response.data);
|
||
},
|
||
cacheTimeout: const Duration(hours: 1), // 配置缓存时间
|
||
);
|
||
```
|
||
|
||
### 日志配置
|
||
|
||
新增统一的日志系统,支持级别控制和自定义处理器:
|
||
|
||
```dart
|
||
final config = YxOSSConfig(
|
||
authProvider: authProvider,
|
||
configProvider: configProvider,
|
||
logConfig: LogConfig(
|
||
enabled: true,
|
||
level: LogLevel.warning, // 只记录警告及以上级别
|
||
logRequest: false, // 是否记录HTTP请求
|
||
logResponse: false, // 是否记录HTTP响应
|
||
logError: true, // 是否记录错误
|
||
customHandler: (message, level) {
|
||
// 自定义日志处理,可接入你的日志系统
|
||
myLogger.log(level.name, message);
|
||
},
|
||
),
|
||
);
|
||
```
|
||
|
||
### 上传选项
|
||
|
||
```dart
|
||
final options = UploadOptions(
|
||
// 基础选项
|
||
overwrite: true, // 是否覆盖同名文件
|
||
contentType: 'image/jpeg', // 文件MIME类型
|
||
enableResume: true, // 启用断点续传
|
||
|
||
// 访问控制
|
||
acl: ACLMode.publicRead, // 访问权限
|
||
storageClass: StorageClass.standard, // 存储类型
|
||
|
||
// 自定义元数据
|
||
metadata: {
|
||
'author': 'YX OSS',
|
||
'version': '1.0.0',
|
||
},
|
||
|
||
// 分片上传配置
|
||
enableMultipart: true, // 启用分片上传
|
||
partSize: 10 * 1024 * 1024, // 分片大小 (10MB)
|
||
multipartThreshold: 100 * 1024 * 1024, // 分片阈值 (100MB)
|
||
concurrency: 3, // 并发上传数
|
||
|
||
// 回调函数
|
||
callbacks: UploadCallbacks(
|
||
onStart: () => print('开始上传'),
|
||
onProgress: (sent, total) {
|
||
final progress = (sent / total * 100).toStringAsFixed(1);
|
||
print('上传进度: $progress%');
|
||
},
|
||
onSuccess: (result) => print('上传成功: ${result.url}'),
|
||
onError: (error) => print('上传失败: ${error.message}'),
|
||
onComplete: () => print('上传完成'),
|
||
),
|
||
);
|
||
```
|
||
|
||
### 断点续传
|
||
|
||
支持大文件的断点续传功能:
|
||
|
||
```dart
|
||
// 启用断点续传的上传
|
||
final result = await client.uploadFile(
|
||
largeFilePath,
|
||
options: UploadOptions(
|
||
enableResume: true,
|
||
callbacks: UploadCallbacks(
|
||
onProgress: (sent, total) {
|
||
print('断点续传进度: ${(sent/total*100).toInt()}%');
|
||
},
|
||
),
|
||
),
|
||
);
|
||
|
||
// 获取可恢复的上传任务
|
||
final resumableTasks = await client.getResumableTasks();
|
||
for (final task in resumableTasks) {
|
||
print('可恢复任务: ${task.objectKey}, 进度: ${task.uploadedSize}/${task.totalSize}');
|
||
}
|
||
|
||
// 恢复指定任务
|
||
final resumeResult = await client.resumeUpload(taskId);
|
||
|
||
// 清理过期的断点续传数据
|
||
await client.cleanupExpiredData(maxAgeDays: 7);
|
||
```
|
||
|
||
### 错误处理
|
||
|
||
库提供了完整的错误类型定义:
|
||
|
||
```dart
|
||
try {
|
||
final result = await client.uploadBytes(data, 'file.txt');
|
||
print('上传成功: ${result.url}');
|
||
} catch (e) {
|
||
if (e is OSSError) {
|
||
switch (e.type) {
|
||
case OSSErrorType.network:
|
||
print('网络错误: ${e.message}');
|
||
break;
|
||
case OSSErrorType.authentication:
|
||
print('认证错误: ${e.message}');
|
||
break;
|
||
case OSSErrorType.permission:
|
||
print('权限错误: ${e.message}');
|
||
break;
|
||
case OSSErrorType.server:
|
||
print('服务器错误: ${e.message}');
|
||
break;
|
||
default:
|
||
print('其他错误: ${e.message}');
|
||
}
|
||
|
||
// 检查是否可重试
|
||
if (e.isRetryable) {
|
||
print('此错误可以重试');
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 🔧 高级配置
|
||
|
||
### 完整配置示例
|
||
|
||
```dart
|
||
final config = YxOSSConfig(
|
||
authProvider: authProvider,
|
||
configProvider: configProvider,
|
||
|
||
// 超时配置
|
||
timeoutConfig: TimeoutConfig(
|
||
connectTimeout: 30000, // 30秒连接超时
|
||
sendTimeout: 600000, // 10分钟发送超时
|
||
receiveTimeout: 600000, // 10分钟接收超时
|
||
),
|
||
|
||
// 重试配置
|
||
retryConfig: RetryConfig(
|
||
maxRetries: 5, // 最多重试5次
|
||
initialInterval: 500, // 初始间隔500ms
|
||
backoffMultiplier: 2.0, // 指数退避因子
|
||
maxInterval: 30000, // 最大间隔30秒
|
||
enableExponentialBackoff: true, // 启用指数退避
|
||
),
|
||
|
||
// 日志配置
|
||
logConfig: LogConfig(
|
||
enabled: true,
|
||
level: LogLevel.debug,
|
||
logRequest: true, // 记录请求详情
|
||
logResponse: true, // 记录响应详情
|
||
logError: true, // 记录错误详情
|
||
customHandler: (message, level) {
|
||
// 自定义日志处理
|
||
print('[YX_OSS] ${level.name.toUpperCase()}: $message');
|
||
},
|
||
),
|
||
);
|
||
```
|
||
|
||
## 🏗️ 项目集成
|
||
|
||
### 使用项目集成适配器
|
||
|
||
库提供了现成的项目集成适配器,可以快速集成到现有项目中:
|
||
|
||
```dart
|
||
// 1. 实现服务器API接口
|
||
class MyOSSApiImpl implements YxOssServerInterface {
|
||
@override
|
||
Future<YxOSSConfigModel> getOssConfig() async {
|
||
// 从你的后端获取OSS配置
|
||
final response = await http.get('/api/oss-config');
|
||
return YxOSSConfigModel.fromJson(response.data);
|
||
}
|
||
|
||
@override
|
||
Future<YxOSSSignModel> getOssSign({String? objectName, int? type}) async {
|
||
// 从你的后端获取预签名URL
|
||
final response = await http.post('/api/oss-sign', {
|
||
'objectName': objectName,
|
||
'type': type,
|
||
});
|
||
return YxOSSSignModel.fromJson(response.data);
|
||
}
|
||
|
||
@override
|
||
Future<bool> deleteOSSFile({required String filePath}) async {
|
||
// 删除文件
|
||
final response = await http.delete('/api/oss-file', {
|
||
'filePath': filePath,
|
||
});
|
||
return response.statusCode == 200;
|
||
}
|
||
}
|
||
|
||
// 2. 使用项目集成管理器
|
||
final ossManager = ProjectOSSManager(MyOSSApiImpl());
|
||
await ossManager.initialize();
|
||
|
||
// 3. 上传文件(自动使用预签名URL)
|
||
final fileUrl = await ossManager.uploadFile(
|
||
filePath,
|
||
onProgress: (sent, total) {
|
||
print('上传进度: ${(sent/total*100).toInt()}%');
|
||
},
|
||
type: 1, // 文件类型:1-普通上传,2-资料收集等
|
||
);
|
||
|
||
// 4. 上传字节数组
|
||
final fileUrl = await ossManager.uploadBytes(
|
||
fileBytes,
|
||
'example.jpg',
|
||
onProgress: (sent, total) => print('进度: $sent/$total'),
|
||
type: 1,
|
||
);
|
||
|
||
// 5. 删除文件
|
||
final success = await ossManager.deleteFile(fileUrl);
|
||
|
||
// 6. 断点续传相关
|
||
final tasks = await ossManager.getResumableTasks();
|
||
final resumeResult = await ossManager.resumeUpload(taskId);
|
||
await ossManager.cleanupExpiredData(maxAgeDays: 7);
|
||
```
|
||
|
||
### 集成到应用生命周期
|
||
|
||
```dart
|
||
class MyApp extends StatefulWidget {
|
||
@override
|
||
_MyAppState createState() => _MyAppState();
|
||
}
|
||
|
||
class _MyAppState extends State<MyApp> {
|
||
late final ProjectOSSManager ossManager;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
ossManager = ProjectOSSManager(MyOSSApiImpl());
|
||
}
|
||
|
||
Future<void> initializeOSS() async {
|
||
try {
|
||
await ossManager.initialize();
|
||
print('OSS初始化成功');
|
||
} catch (e) {
|
||
print('OSS初始化失败: $e');
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
ossManager.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
// ... 其他代码
|
||
}
|
||
```
|
||
|
||
## 🌍 区域支持
|
||
|
||
库内置了常用的阿里云OSS区域配置:
|
||
|
||
```dart
|
||
// 中国大陆区域
|
||
CommonRegions.hangzhou // 华东1 (杭州)
|
||
CommonRegions.beijing // 华北2 (北京)
|
||
CommonRegions.shanghai // 华东2 (上海)
|
||
CommonRegions.shenzhen // 华南1 (深圳)
|
||
CommonRegions.chengdu // 西南1 (成都)
|
||
|
||
// 海外区域
|
||
CommonRegions.singapore // 亚太东南1 (新加坡)
|
||
CommonRegions.sydney // 亚太东南2 (悉尼)
|
||
CommonRegions.tokyo // 亚太东北1 (东京)
|
||
CommonRegions.virginia // 美国东部1 (弗吉尼亚)
|
||
CommonRegions.london // 欧洲西部1 (伦敦)
|
||
```
|
||
|
||
## 🔄 迁移指南
|
||
|
||
### 从Legacy OSS迁移
|
||
|
||
如果你正在从现有的OSS实现迁移到YX OSS:
|
||
|
||
#### 原项目代码
|
||
```dart
|
||
// 原项目可能是这样的
|
||
final ossClient = AliyunOssClientUtils();
|
||
await ossClient.uploadFile(file, fileName);
|
||
```
|
||
|
||
#### YX OSS代码
|
||
```dart
|
||
// 迁移到YX OSS - 使用项目集成适配器
|
||
final ossManager = ProjectOSSManager(apiImpl);
|
||
await ossManager.initialize();
|
||
final fileUrl = await ossManager.uploadFile(filePath);
|
||
```
|
||
|
||
#### 迁移优势
|
||
|
||
1. **解耦合**: YX OSS是完全独立的库,不依赖项目特定的代码
|
||
2. **更好的错误处理**: 类型安全的错误处理机制
|
||
3. **断点续传**: 完整的断点续传支持
|
||
4. **灵活配置**: 支持多种认证和配置方式
|
||
5. **统一日志**: 可配置的日志系统
|
||
6. **更好的测试**: 所有组件都可以独立测试
|
||
|
||
## 📚 API文档
|
||
|
||
### 核心类
|
||
|
||
- `YxOSSClient` - OSS客户端主类
|
||
- `YxOSSConfig` - 客户端配置
|
||
- `ProjectOSSManager` - 项目集成管理器
|
||
|
||
### 接口
|
||
|
||
- `AuthProvider` - 认证提供者接口
|
||
- `ConfigProvider` - 配置提供者接口
|
||
- `ResumeStorage` - 断点续传存储接口
|
||
- `YxOssServerInterface` - 服务器API接口
|
||
|
||
### 模型
|
||
|
||
- `UploadOptions` - 上传选项
|
||
- `UploadResult` - 上传结果
|
||
- `OSSError` - 错误类型
|
||
|
||
### 工具
|
||
|
||
- `YxOSSFileUtils` - 文件工具类
|
||
- `OssLogger` - 日志工具
|
||
|
||
## 🧪 测试
|
||
|
||
```dart
|
||
// 运行测试
|
||
flutter test
|
||
|
||
// 运行集成测试
|
||
flutter test integration_test/
|
||
```
|
||
|
||
|
||
|
||
### 开发环境设置
|
||
|
||
1. Fork 项目
|
||
2. 创建功能分支
|
||
3. 提交更改
|
||
4. 创建 Pull Request
|
||
|
||
|
||
|
||
## 📈 更新日志
|
||
|
||
### v1.0.0
|
||
- ✅ 核心OSS上传下载功能
|
||
- ✅ 多种认证方式支持
|
||
- ✅ 断点续传功能
|
||
- ✅ 项目集成适配器
|
||
- ✅ 统一日志系统
|
||
- ✅ 完整的错误处理
|
||
- ✅ 类型安全的API设计
|
||
|
||
---
|
||
|
||
**YX OSS** - 让 Flutter OSS 上传更简单、更可靠! 🚀
|