初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:hgdj/tools_base/debug_log.dart';
import 'package:http/http.dart' hide Response;
import '../../extension/extensions.dart';
import '../../hj_utils/file_util.dart';
import '../net/load_apk/dio_cli.dart';
import 'cancel_token_manager.dart';
/// dio 文件下载器(视频流缓存的 FileService
class DioFileService extends FileService {
/// 真正请求的 dio
final _dio = createDio();
@override
Future<FileServiceResponse> get(String url,
{Map<String, String>? headers = const {}}) async {
// cancelToken 用文件名注册、下载结束后按同一 key 移除
//(原来 createToken 用 name 而 remove 用 url,key 不一致:既移不掉导致泄漏,又会 firstWhere 抛 StateError
final name = FileUtil.getName(url);
final token = CancelTokenManager().createToken(name);
// 每次请求用独立 Options:本类随 VideoCacheManager 单例,共享一份 Options 会被并发请求互相覆盖 headers
final options = Options(
method: 'GET',
sendTimeout: const Duration(milliseconds: 5000),
receiveTimeout: const Duration(milliseconds: 10000),
headers: {...?headers, 'cache-control': 'max-age=31104000'},
contentType: ContentType.binary.toString(),
responseType: ResponseType.stream,
);
Response<ResponseBody>? resp;
try {
debugLog("DioFileService get: $url");
resp = await _dio.get<ResponseBody>(url,
cancelToken: token, options: options);
} catch (e) {
debugLog("DioFileService get error: $url -> $e");
} finally {
CancelTokenManager().remove(name);
}
// 只认 200/206;其余(含请求异常 resp==null)直接抛:避免返回空流挂起、坏响应被缓存
final statusCode = resp?.statusCode ?? HttpStatus.badRequest;
if (resp?.data == null || (statusCode != 200 && statusCode != 206)) {
throw HttpException("video chunk fetch failed ($statusCode): $url");
}
final respHeaders = <String, String>{};
resp!.headers.forEach((key, values) {
if (values.notEmpty()) respHeaders[key] = values.first;
});
// Content-Length 可能缺失/非数字,安全解析(原 contentLengthS[0] 在空串时会 RangeError);缺失传 null 表示长度未知
final contentLength =
int.tryParse(respHeaders[Headers.contentLengthHeader] ?? '');
debugLog(
"DioFileService resp($statusCode): $url contentLength:$contentLength");
return HttpGetResponse(StreamedResponse(
resp.data!.stream,
statusCode,
headers: respHeaders,
contentLength: contentLength,
));
}
}