import 'dart:typed_data'; import 'package:yx_oss/yx_oss.dart'; /// YX OSS 使用示例 /// /// 展示如何使用不同的认证和配置方式 void main() async { print('YX OSS 使用示例'); // 示例1: 静态配置 + 静态认证 await example1StaticAuth(); // 示例2: STS临时凭证认证 await example2STSAuth(); // 示例3: 预签名URL认证 await example3PreSignedAuth(); // 示例4: 动态配置 await example4DynamicConfig(); // 示例5: 分片上传 await example5MultipartUpload(); } /// 示例1: 静态配置 + 静态认证 /// 适用场景: 开发测试环境,简单的应用场景 Future example1StaticAuth() async { print('\n=== 示例1: 静态配置 + 静态认证 ==='); // 创建静态认证提供者 const authProvider = StaticAuthProvider( accessKeyId: 'your_access_key_id', accessKeySecret: 'your_access_key_secret', ); // 创建静态配置提供者 const configProvider = StaticConfigProvider( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'your-bucket-name', directory: 'uploads', // 可选,默认为'uploads' domain: 'https://your-custom-domain.com', // 可选,自定义域名 ); // 创建OSS客户端配置 const config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, // 可选的超时配置 timeoutConfig: TimeoutConfig( connectTimeout: 60000, sendTimeout: 300000, receiveTimeout: 300000, ), // 可选的重试配置 retryConfig: RetryConfig( maxRetries: 3, initialInterval: 1000, enableExponentialBackoff: true, ), // 可选的日志配置 logConfig: LogConfig( enabled: true, level: LogLevel.info, logRequest: false, logResponse: false, logError: true, ), ); // 创建OSS客户端 final client = YxOSSClient(config); try { // 初始化客户端 await client.initialize(); // 准备上传的文件数据 final fileData = Uint8List.fromList('Hello, YX OSS!'.codeUnits); // 创建上传选项 final options = UploadOptions( overwrite: true, acl: ACLMode.publicRead, storageClass: StorageClass.standard, contentType: 'text/plain', metadata: {'author': 'YX OSS Example'}, callbacks: UploadCallbacks( onStart: () => print('开始上传...'), onProgress: (sent, total) { final progress = (sent / total * 100).toStringAsFixed(1); print('上传进度: $progress% ($sent/$total)'); }, onSuccess: (result) => print('上传成功: ${result.url}'), onError: (error) => print('上传失败: $error'), onComplete: () => print('上传完成'), ), ); // 执行上传 final result = await client.uploadBytes( fileData, 'examples/test-file.txt', options: options, ); print('上传结果:'); print(' URL: ${result.url}'); print(' 对象键: ${result.objectKey}'); print(' 文件大小: ${result.fileSize} 字节'); print(' ETag: ${result.etag}'); print(' 上传耗时: ${result.uploadDuration} 毫秒'); } catch (e) { print('操作失败: $e'); } finally { // 释放资源 client.dispose(); } } /// 示例2: STS临时凭证认证 /// 适用场景: 生产环境,需要动态权限控制 Future example2STSAuth() async { print('\n=== 示例2: STS临时凭证认证 ==='); // 模拟从服务器获取STS凭证的函数 Future getSTSCredentials() async { // 实际应用中,这里应该调用您的后端API获取STS凭证 // 这里只是示例数据 return STSCredentials( accessKeyId: 'STS.your_sts_access_key_id', accessKeySecret: 'your_sts_access_key_secret', securityToken: 'your_security_token', expiration: DateTime.now().add(const Duration(hours: 1)), ); } // 创建STS认证提供者 final stsCredentials = await getSTSCredentials(); final authProvider = STSAuthProvider( accessKeyId: stsCredentials.accessKeyId, accessKeySecret: stsCredentials.accessKeySecret, securityToken: stsCredentials.securityToken, expiration: stsCredentials.expiration, credentialsGetter: getSTSCredentials, // 凭证过期时自动刷新 ); const configProvider = StaticConfigProvider( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'your-bucket-name', directory: 'sts-uploads', ); final config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, ); final client = YxOSSClient(config); try { await client.initialize(); final fileData = Uint8List.fromList('STS upload test'.codeUnits); final result = await client.uploadBytes( fileData, 'sts-test-file.txt', options: UploadOptions( callbacks: UploadCallbacks( onProgress: (sent, total) { print('STS上传进度: ${(sent / total * 100).toStringAsFixed(1)}%'); }, ), ), ); print('STS上传成功: ${result.url}'); } catch (e) { print('STS上传失败: $e'); } finally { client.dispose(); } } /// 示例3: 预签名URL认证 /// 适用场景: 客户端直接上传,服务端控制权限 Future example3PreSignedAuth() async { print('\n=== 示例3: 预签名URL认证 ==='); // 模拟从服务器获取预签名URL的函数 Future getPreSignedUrl(String fileName) async { // 实际应用中,这里应该调用您的后端API获取预签名URL // 后端会根据文件名和权限策略生成预签名URL return 'https://your-bucket.oss-cn-hangzhou.aliyuncs.com/uploads/$fileName?Expires=1234567890&OSSAccessKeyId=your_key&Signature=signature'; } // 创建预签名URL认证提供者 final authProvider = PreSignedAuthProvider( urlGetter: getPreSignedUrl, ); // 注意:预签名URL模式下,配置提供者仍然需要,但某些配置可能不会被使用 const configProvider = StaticConfigProvider( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'your-bucket-name', directory: '', // 预签名URL通常已包含完整路径 ); final config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, ); final client = YxOSSClient(config); try { await client.initialize(); final fileData = Uint8List.fromList('PreSigned URL upload test'.codeUnits); final result = await client.uploadBytes( fileData, 'presigned-test-file.txt', options: UploadOptions( callbacks: UploadCallbacks( onProgress: (sent, total) { print('预签名上传进度: ${(sent / total * 100).toStringAsFixed(1)}%'); }, ), ), ); print('预签名上传成功: ${result.url}'); } catch (e) { print('预签名上传失败: $e'); } finally { client.dispose(); } } /// 示例4: 动态配置 /// 适用场景: 配置信息需要从服务器动态获取 Future example4DynamicConfig() async { print('\n=== 示例4: 动态配置 ==='); // 模拟从服务器获取OSS配置的函数 Future getOSSConfig() async { // 实际应用中,这里应该调用您的后端API获取OSS配置 return const OSSConfig( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'dynamic-bucket-name', directory: 'dynamic-uploads', domain: 'https://cdn.example.com', ); } const authProvider = StaticAuthProvider( accessKeyId: 'your_access_key_id', accessKeySecret: 'your_access_key_secret', ); // 创建动态配置提供者 final configProvider = DynamicConfigProvider( configGetter: getOSSConfig, cacheTimeout: const Duration(minutes: 30), // 配置缓存30分钟 ); final config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, ); final client = YxOSSClient(config); try { await client.initialize(); final fileData = Uint8List.fromList('Dynamic config upload test'.codeUnits); final result = await client.uploadBytes( fileData, 'dynamic-config-test.txt', options: UploadOptions( callbacks: UploadCallbacks( onProgress: (sent, total) { print('动态配置上传进度: ${(sent / total * 100).toStringAsFixed(1)}%'); }, ), ), ); print('动态配置上传成功: ${result.url}'); } catch (e) { print('动态配置上传失败: $e'); } finally { client.dispose(); } } /// 示例5: 分片上传 /// 适用场景: 大文件上传,需要支持断点续传和并发上传 Future example5MultipartUpload() async { print('\n=== 示例5: 分片上传 ==='); const authProvider = StaticAuthProvider( accessKeyId: 'your_access_key_id', accessKeySecret: 'your_access_key_secret', ); const configProvider = StaticConfigProvider( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'your-bucket-name', directory: 'large-files', ); const config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, ); final client = YxOSSClient(config); try { await client.initialize(); // 模拟大文件数据(200MB) final largeFileData = Uint8List(200 * 1024 * 1024); for (int i = 0; i < largeFileData.length; i++) { largeFileData[i] = i % 256; } print( '准备上传 ${YxOSSFileUtils.formatFileSize(largeFileData.length)} 的大文件...'); final options = UploadOptions( // 启用分片上传 enableMultipart: true, // 分片大小设置为10MB partSize: 10 * 1024 * 1024, // 并发上传3个分片 concurrency: 3, // 100MB以上的文件使用分片上传 multipartThreshold: 100 * 1024 * 1024, callbacks: UploadCallbacks( onStart: () => print('开始分片上传...'), onProgress: (sent, total) { final progress = (sent / total * 100).toStringAsFixed(1); final speed = YxOSSFileUtils.formatFileSize(sent ~/ 10); // 假设10秒速度 print('分片上传进度: $progress% - 速度: $speed'); }, onSuccess: (result) { if (result is MultipartUploadResult) { print('分片上传成功:'); print(' URL: ${result.url}'); print(' 分片数量: ${result.partCount}'); print(' 上传ID: ${result.uploadId}'); print(' 总耗时: ${result.uploadDuration} 毫秒'); } }, onError: (error) => print('分片上传失败: $error'), onComplete: () => print('分片上传完成'), ), ); final result = await client.uploadBytes( largeFileData, 'large-file-${DateTime.now().millisecondsSinceEpoch}.dat', options: options, ); print('大文件上传结果: ${result.url}'); } catch (e) { print('大文件上传失败: $e'); } finally { client.dispose(); } } /// 示例6: 错误处理和重试 Future example6ErrorHandling() async { print('\n=== 示例6: 错误处理和重试 ==='); const authProvider = StaticAuthProvider( accessKeyId: 'invalid_key', // 故意使用错误的key来演示错误处理 accessKeySecret: 'invalid_secret', ); const configProvider = StaticConfigProvider( endpoint: 'oss-cn-hangzhou.aliyuncs.com', bucketName: 'your-bucket-name', ); const config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, // 配置重试策略 retryConfig: RetryConfig( maxRetries: 3, initialInterval: 1000, backoffMultiplier: 2.0, enableExponentialBackoff: true, ), ); final client = YxOSSClient(config); try { await client.initialize(); final fileData = Uint8List.fromList('Error handling test'.codeUnits); await client.uploadBytes( fileData, 'error-test.txt', options: UploadOptions( callbacks: UploadCallbacks( onError: (error) { print('捕获到错误:'); print(' 类型: ${error.type}'); print(' 消息: ${error.message}'); print(' 状态码: ${error.statusCode ?? 'N/A'}'); print(' 请求ID: ${error.requestId ?? 'N/A'}'); print(' 是否可重试: ${error.isRetryable}'); }, ), ), ); } catch (e) { if (e is OSSError) { print('OSS错误详情:'); print(' 错误类型: ${e.type}'); print(' 错误代码: ${e.code}'); print(' 错误消息: ${e.message}'); print(' HTTP状态码: ${e.statusCode}'); print(' 是否为认证错误: ${e.isAuthenticationError}'); print(' 是否为网络错误: ${e.isNetworkError}'); } else { print('未知错误: $e'); } } finally { client.dispose(); } } /// 示例7: 集成到项目中的适配器模式 class ProjectOSSAdapter { late final YxOSSClient _client; /// 初始化适配器 Future initialize({ required String endpoint, required String bucketName, required String accessKeyId, required String accessKeySecret, String? customDomain, }) async { final authProvider = StaticAuthProvider( accessKeyId: accessKeyId, accessKeySecret: accessKeySecret, ); final configProvider = StaticConfigProvider( endpoint: endpoint, bucketName: bucketName, directory: 'app-uploads', domain: customDomain, ); final config = YxOSSConfig( authProvider: authProvider, configProvider: configProvider, logConfig: const LogConfig( enabled: true, level: LogLevel.warning, // 生产环境只记录警告和错误 ), ); _client = YxOSSClient(config); await _client.initialize(); } /// 上传图片文件 Future uploadImage( Uint8List imageData, String fileName, { Function(double progress)? onProgress, }) async { final result = await _client.uploadBytes( imageData, 'images/${YxOSSFileUtils.generateUniqueFileName(originalFileName: fileName)}', options: UploadOptions( contentType: YxOSSFileUtils.guessMimeType(fileName), acl: ACLMode.publicRead, callbacks: UploadCallbacks( onProgress: (sent, total) { onProgress?.call(sent / total); }, ), ), ); return result.url; } /// 上传文档文件 Future uploadDocument( Uint8List documentData, String fileName, { Function(double progress)? onProgress, }) async { final result = await _client.uploadBytes( documentData, 'documents/${YxOSSFileUtils.generateUniqueFileName(originalFileName: fileName)}', options: UploadOptions( contentType: YxOSSFileUtils.guessMimeType(fileName), acl: ACLMode.private, // 文档默认私有 callbacks: UploadCallbacks( onProgress: (sent, total) { onProgress?.call(sent / total); }, ), ), ); return result.url; } /// 释放资源 void dispose() { _client.dispose(); } }