Files
2026-09-15 15:44:13 +07:00

72 lines
2.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
));
}
}