import 'dart:async'; import 'dart:io'; import 'package:autosos_flutter/api/upload_api.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; /// 七牛文件上传服务(对应 Android QiNiuEntity + Qiniu SDK) class UploadService { static final UploadService instance = UploadService._(); UploadService._(); final _dio = Dio(BaseOptions( connectTimeout: const Duration(seconds: 30), receiveTimeout: const Duration(seconds: 60), )); /// 上传单个文件,返回远端 URL Future upload(String localPath) async { final tokenResp = await UploadApi.instance.qiNiuToken(); if (!tokenResp.isSuccess) { throw Exception('获取七牛凭证失败: ${tokenResp.message}'); } final token = tokenResp.data!; final form = FormData.fromMap({ 'token': token.token, 'file': await MultipartFile.fromFile(localPath), }); final url = 'http://up.qiniup.com/'; // 七牛华东上传地址 final r = await _dio.post(url, data: form, options: Options(responseType: ResponseType.json)); final data = r.data is Map ? r.data as Map : {}; final key = data['key'] as String?; if (key == null) throw Exception('七牛返回 key 为空'); final domain = token.domain.endsWith('/') ? token.domain : '${token.domain}/'; return '$domain$key'; } /// 批量上传(并发 3 个) Future> uploadBatch(List localPaths, {int concurrency = 3}) async { final results = []; final pool = >[]; int cursor = 0; Future worker() async { while (cursor < localPaths.length) { final i = cursor++; try { results[i] = await upload(localPaths[i]); } catch (e) { debugPrint('uploadBatch index=$i failed: $e'); results[i] = null; } } } for (int i = 0; i < concurrency && i < localPaths.length; i++) { pool.add(worker()); } await Future.wait(pool); if (results.contains(null)) { throw Exception('部分文件上传失败: $results'); } return results.cast(); } /// 上传并校验文件存在 Future uploadSafe(String localPath) async { if (!await File(localPath).exists()) return null; try { return await upload(localPath); } catch (e) { debugPrint('uploadSafe failed: $e'); return null; } } }