/// OSS配置提供者接口 /// /// 定义获取OSS配置信息的标准接口,支持动态配置和静态配置 abstract class ConfigProvider { /// 获取OSS端点 Future getEndpoint(); /// 获取存储桶名称 Future getBucketName(); /// 获取上传目录前缀 Future getDirectory(); /// 获取访问域名 /// 如果为null,则使用默认的 https://{bucket}.{endpoint} Future getDomain(); /// 获取配置信息是否有效 Future isValid(); /// 刷新配置信息 Future refresh(); } /// 静态配置提供者 /// 使用固定的配置信息 class StaticConfigProvider implements ConfigProvider { final String endpoint; final String bucketName; final String directory; final String? domain; const StaticConfigProvider({ required this.endpoint, required this.bucketName, this.directory = 'uploads', this.domain, }); @override Future getEndpoint() async => endpoint; @override Future getBucketName() async => bucketName; @override Future getDirectory() async => directory; @override Future getDomain() async => domain; @override Future isValid() async => true; @override Future refresh() async { // 静态配置不需要刷新 } } /// 动态配置提供者 /// 支持从服务端动态获取配置信息 class DynamicConfigProvider implements ConfigProvider { OSSConfig? _config; DateTime? _lastUpdate; final Duration _cacheTimeout; final Future Function() _configGetter; DynamicConfigProvider({ required Future Function() configGetter, Duration cacheTimeout = const Duration(hours: 1), }) : _configGetter = configGetter, _cacheTimeout = cacheTimeout; @override Future getEndpoint() async { await _ensureConfig(); return _config!.endpoint; } @override Future getBucketName() async { await _ensureConfig(); return _config!.bucketName; } @override Future getDirectory() async { await _ensureConfig(); return _config!.directory; } @override Future getDomain() async { await _ensureConfig(); return _config!.domain; } @override Future isValid() async { if (_config == null || _lastUpdate == null) return false; return DateTime.now().difference(_lastUpdate!) < _cacheTimeout; } @override Future refresh() async { _config = await _configGetter(); _lastUpdate = DateTime.now(); } /// 确保配置信息有效 Future _ensureConfig() async { if (!await isValid()) { await refresh(); } } } /// OSS配置模型 class OSSConfig { final String endpoint; final String bucketName; final String directory; final String? domain; const OSSConfig({ required this.endpoint, required this.bucketName, this.directory = 'uploads', this.domain, }); factory OSSConfig.fromJson(Map json) { return OSSConfig( endpoint: json['endpoint'] as String, bucketName: json['bucketName'] as String, directory: json['directory'] as String? ?? 'uploads', domain: json['domain'] as String?, ); } Map toJson() { return { 'endpoint': endpoint, 'bucketName': bucketName, 'directory': directory, if (domain != null) 'domain': domain, }; } }