80 lines
2.4 KiB
Dart
80 lines
2.4 KiB
Dart
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<String> 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<String>(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<List<String>> uploadBatch(List<String> localPaths, {int concurrency = 3}) async {
|
||
final results = <String?>[];
|
||
final pool = <Future<void>>[];
|
||
|
||
int cursor = 0;
|
||
Future<void> 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<String>();
|
||
}
|
||
|
||
/// 上传并校验文件存在
|
||
Future<String?> uploadSafe(String localPath) async {
|
||
if (!await File(localPath).exists()) return null;
|
||
try {
|
||
return await upload(localPath);
|
||
} catch (e) {
|
||
debugPrint('uploadSafe failed: $e');
|
||
return null;
|
||
}
|
||
}
|
||
} |