jjsos_autosos_flutter/lib/service/upload_service.dart

80 lines
2.4 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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