yx_oss_flutter/README.md

14 KiB
Raw Permalink Blame History

YX OSS

pub package documentation license

一个专注于核心功能的阿里云 OSS (Object Storage Service) Flutter 客户端库,提供纯净的文件上传下载能力。

🎯 设计理念

单一职责:本库专注于 OSS 核心操作 - 文件上传、下载和管理。故意排除了 UI 组件、图片压缩、文件选择等功能,保持简洁性和灵活性。

最小依赖:仅包含 OSS 操作的必需依赖,让您可以自由选择自己的 UI 和工具库。

核心特性

认证与配置

  • 🔐 多种认证方式静态密钥、STS临时凭证、预签名URL
  • ⚙️ 动态配置:运行时配置更新和缓存
  • 🔌 可插拔提供者:灵活的认证和配置提供者架构

上传与下载

  • 📤 断点续传:支持大文件的断点续传,本地存储断点信息
  • 🧩 分片上传:大文件自动分片处理,支持并发上传
  • 📊 进度监控:实时上传下载进度跟踪
  • 预签名URL:支持客户端直接上传,服务端控制权限

可靠性与错误处理

  • 🔄 重试机制:指数退避重试失败操作
  • 🛡️ 类型安全错误处理:完整的错误类型和处理
  • 取消支持:可取消正在进行的操作
  • 📝 统一日志:可配置的日志系统,支持自定义处理器

架构特点

  • 🎯 零耦合:不依赖特定项目架构
  • 📱 跨平台:支持 iOS、Android、Web、Desktop
  • 🏗️ 清洁架构:依赖注入和关注点分离
  • 🔧 项目集成:提供现成的项目集成适配器

🚀 快速开始

安装

在你的 pubspec.yaml 文件中添加依赖:

dependencies:
  yx_oss: ^1.0.0

然后运行:

flutter pub get

基础用法

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)

适用于开发测试环境或简单应用场景:

final authProvider = StaticAuthProvider(
  accessKeyId: 'your_access_key_id',
  accessKeySecret: 'your_access_key_secret',
);

2. STS临时凭证 (STS Authentication)

适用于生产环境,提供更安全的权限控制:

// 从服务器获取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获取配置

// 使用项目集成适配器
final manager = ProjectOSSManager(myApiImpl);
await manager.initialize();

// 直接使用,自动处理认证和配置
final fileUrl = await manager.uploadFile(
  filePath,
  onProgress: (sent, total) => print('进度: $sent/$total'),
  type: 1, // 文件类型
);

配置管理

1. 静态配置 (Static Configuration)

final configProvider = StaticConfigProvider(
  endpoint: 'oss-cn-hangzhou.aliyuncs.com',
  bucketName: 'your-bucket-name',
  directory: 'uploads',
  domain: 'https://your-custom-domain.com', // 可选
);

2. 动态配置 (Dynamic Configuration)

支持从服务器动态获取配置,适用于多环境部署:

final configProvider = DynamicConfigProvider(
  configGetter: () async {
    final response = await http.get('/api/oss-config');
    return OSSConfig.fromJson(response.data);
  },
  cacheTimeout: const Duration(hours: 1), // 配置缓存时间
);

日志配置

新增统一的日志系统,支持级别控制和自定义处理器:

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);
    },
  ),
);

上传选项

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('上传完成'),
  ),
);

断点续传

支持大文件的断点续传功能:

// 启用断点续传的上传
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);

错误处理

库提供了完整的错误类型定义:

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('此错误可以重试');
    }
  }
}

🔧 高级配置

完整配置示例

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');
    },
  ),
);

🏗️ 项目集成

使用项目集成适配器

库提供了现成的项目集成适配器,可以快速集成到现有项目中:

// 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);

集成到应用生命周期

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区域配置

// 中国大陆区域
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

原项目代码

// 原项目可能是这样的
final ossClient = AliyunOssClientUtils();
await ossClient.uploadFile(file, fileName);

YX OSS代码

// 迁移到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 - 日志工具

🧪 测试

// 运行测试
flutter test

// 运行集成测试
flutter test integration_test/

开发环境设置

  1. Fork 项目
  2. 创建功能分支
  3. 提交更改
  4. 创建 Pull Request

📈 更新日志

v1.0.0

  • 核心OSS上传下载功能
  • 多种认证方式支持
  • 断点续传功能
  • 项目集成适配器
  • 统一日志系统
  • 完整的错误处理
  • 类型安全的API设计

YX OSS - 让 Flutter OSS 上传更简单、更可靠! 🚀