| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- import 'dart:io';
- import 'dart:convert';
- import 'package:crypto/crypto.dart';
- import 'package:dio/io.dart';
- import 'package:path/path.dart' as path;
- import 'package:dio/dio.dart';
- import 'developer/ix_developer_tools.dart';
- class FileStreamUtils {
- static const int defaultBufferSize = 64 * 1024;
- static final Dio dio = Dio();
- static setProxy(String proxy) {
- dio.httpClientAdapter = IOHttpClientAdapter(
- createHttpClient: () {
- final client = HttpClient();
- client.findProxy = (uri) => proxy;
- client.badCertificateCallback =
- (X509Certificate cert, String host, int port) => true;
- return client;
- },
- );
- }
- /// 读取文件(支持本地文件和网络URL)
- /// [path] 文件路径或URL
- /// [encoding] 文件编码,默认UTF8
- /// [onProgress] 读取进度回调
- static Future<FileReadResult> readTextFile({
- required String path,
- Encoding encoding = utf8,
- void Function(double progress)? onProgress,
- }) async {
- if (path.startsWith('http://') || path.startsWith('https://')) {
- return _readFromUrl(
- url: path,
- encoding: encoding,
- onProgress: onProgress,
- );
- } else {
- return _readFromFile(
- filePath: path,
- encoding: encoding,
- onProgress: onProgress,
- );
- }
- }
- /// 从URL读取
- static Future<FileReadResult> _readFromUrl({
- required String url,
- required Encoding encoding,
- void Function(double progress)? onProgress,
- }) async {
- try {
- // 添加talker日志
- dio.interceptors.add(SimpleNoSignApiMonitorInterceptor());
- final response = await dio.get<List<int>>(
- url,
- options: Options(
- responseType: ResponseType.bytes,
- followRedirects: true,
- ),
- onReceiveProgress: (received, total) {
- if (total != -1 && onProgress != null) {
- onProgress(received / total);
- }
- },
- );
- if (response.data == null) {
- throw Exception('No data received');
- }
- final bytes = response.data!;
- final content = encoding.decode(bytes);
- final md5Hash = md5.convert(bytes).toString();
- return FileReadResult(
- content: content,
- md5Hash: md5Hash,
- fileName: path.basename(url),
- fileSize: bytes.length,
- );
- } catch (e) {
- throw Exception('Error downloading file: $e');
- }
- }
- /// 从本地文件读取
- static Future<FileReadResult> _readFromFile({
- required String filePath,
- required Encoding encoding,
- void Function(double progress)? onProgress,
- }) async {
- try {
- final file = File(filePath);
- if (!await file.exists()) {
- throw FileSystemException('File not found', filePath);
- }
- final fileSize = await file.length();
- var bytesRead = 0;
- final List<int> allBytes = [];
- final StringBuffer content = StringBuffer();
- final stream = file.openRead();
- await for (var data in stream) {
- allBytes.addAll(data);
- content.write(encoding.decode(data));
- bytesRead += data.length;
- if (onProgress != null) {
- onProgress(bytesRead / fileSize);
- }
- }
- final md5Hash = md5.convert(allBytes).toString();
- return FileReadResult(
- content: content.toString(),
- md5Hash: md5Hash,
- fileName: path.basename(filePath),
- fileSize: fileSize,
- );
- } catch (e) {
- throw FileSystemException('Error reading file: $e', filePath);
- }
- }
- /// 验证文件或URL的MD5
- static Future<bool> verifyMd5({
- required String path,
- required String expectedMd5,
- void Function(double progress)? onProgress,
- }) async {
- try {
- final result = await readTextFile(path: path, onProgress: onProgress);
- return result.md5Hash.toLowerCase() == expectedMd5.toLowerCase();
- } catch (e) {
- return false;
- }
- }
- /// 获取文件或URL的MD5
- static Future<String?> getMd5({
- required String path,
- void Function(double progress)? onProgress,
- }) async {
- try {
- final result = await readTextFile(path: path, onProgress: onProgress);
- return result.md5Hash;
- } catch (e) {
- return null;
- }
- }
- }
- /// 文件读取结果
- class FileReadResult {
- final String content; // 文件内容
- final String md5Hash; // MD5值
- final String fileName; // 文件名
- final int fileSize; // 文件大小
- FileReadResult({
- required this.content,
- required this.md5Hash,
- required this.fileName,
- required this.fileSize,
- });
- @override
- String toString() {
- return 'FileReadResult{fileName: $fileName, fileSize: $fileSize, md5Hash: $md5Hash}';
- }
- }
|