初始化
This commit is contained in:
+71
@@ -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,
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user