import 'dart:convert'; import 'package:archive/archive.dart'; import 'package:dio/dio.dart'; import 'package:uuid/uuid.dart'; import '../../../utils/crypto.dart'; import '../../../utils/developer/ix_developer_tools.dart'; import '../../../utils/log/logger.dart'; import '../../constants/keys.dart'; import '../../data/models/api_exception.dart'; import '../../data/models/api_result.dart'; import '../../data/sp/ix_sp.dart'; import '../base/base_api.dart'; import '../core/api_core_paths.dart'; /// 核心API class ApiFile extends BaseApi { static final _instance = ApiFile._internal(); factory ApiFile() => _instance; ApiFile._internal() { _initDio(); } /// 初始化Dio void _initDio() { // 此处可以设置默认的DIO参数 final options = BaseOptions(); options.connectTimeout = const Duration(seconds: 90); options.receiveTimeout = const Duration(seconds: 90); options.responseType = ResponseType.bytes; options.headers['content-type'] = 'multipart/form-data'; dio = Dio(options); // 添加talker日志 dio.interceptors.add(SimpleApiMonitorInterceptor()); // 添加拦截器 _setupInterceptors(); } // bool _isRefreshing = false; void _setupInterceptors() { dio.interceptors.add( InterceptorsWrapper( onRequest: (options, handler) async { // 在请求发送前添加token final user = IXSP.getUser(); if (user != null) { options.headers['Authorization'] = user.accessToken; } return handler.next(options); }, onError: (DioException error, handler) async { return handler.next(error); }, ), ); } @override Map? getDefaultHeader() { // 可以设置自定义Header final headers = { 'X-NL-Product-Code': 'nomo', 'X-NL-Content-Encoding': 'gzip', }; return headers; } @override Map? getDefaultQuery() { // 可以设置自定义Query return null; } @override dynamic encrypt(dynamic input) { return input; } @override dynamic decrypt(dynamic input) { try { final decryptedBytes = Crypto.decryptBytes( base64Encode(input), Keys.aesKey, Keys.aesIv, ); // 使用GZip解压 final gzipDecoder = GZipDecoder(); final decodeBytes = gzipDecoder.decodeBytes(decryptedBytes); final data = utf8.decode(decodeBytes); log('ApiCore', '<<:$data'); return jsonDecode(data); } catch (error) { throw ApiException("-2", "decrypt error: $error"); } } // 上传日志文件 Future uploadLogFile( String filePath, String fileName, String logType, String data, ) async { final fileData = await MultipartFile.fromFile(filePath, filename: fileName); const fileType = 'gzip'; final timestamp = DateTime.now().millisecondsSinceEpoch; final sign = Crypto.encrypt( '$fileType$logType$timestamp', Keys.aesKey, Keys.aesIv, ); if (logType == "App_NL_Log") { final logId = const Uuid().v4(); final userInfo = Crypto.encrypt(data, Keys.aesKey, Keys.aesIv); final formData = FormData.fromMap({ 'file': fileData, 'fileName': fileName, 'fileType': fileType, 'logType': logType, 'timestamp': timestamp, 'sign': sign, 'userInfo': userInfo, 'logId': logId, }); return post( ApiCorePaths.uploadFile, data: formData, domainType: DomainType.file, ); } else { final formData = FormData.fromMap({ 'file': fileData, 'fileName': fileName, 'fileType': fileType, 'timestamp': timestamp, 'logType': logType, 'sign': sign, }); return post( ApiCorePaths.uploadFile, data: formData, domainType: DomainType.file, ); } } // 上传图片文件 Future uploadImageFile(String filePath, String fileName) async { final fileData = await MultipartFile.fromFile(filePath, filename: fileName); const fileType = 'image'; final timestamp = DateTime.now().millisecondsSinceEpoch; final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv); final formData = FormData.fromMap({ 'file': fileData, 'fileType': fileType, 'timestamp': timestamp, 'sign': sign, }); return post( ApiCorePaths.uploadImage, data: formData, domainType: DomainType.file, ); } // 上传视频文件 Future uploadVideoFile(String filePath, String fileName) async { final fileData = await MultipartFile.fromFile(filePath, filename: fileName); const fileType = 'video'; final timestamp = DateTime.now().millisecondsSinceEpoch; final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv); final formData = FormData.fromMap({ 'file': fileData, 'fileType': fileType, 'timestamp': timestamp, 'sign': sign, }); return post( ApiCorePaths.uploadVideo, data: formData, domainType: DomainType.file, ); } // 上传多个图片文件 Future uploadMultipleImageFiles( List filePaths, List fileNames, ) async { final List files = []; for (int i = 0; i < filePaths.length; i++) { final fileData = await MultipartFile.fromFile( filePaths[i], filename: fileNames[i], ); files.add(fileData); } const fileType = 'image'; final timestamp = DateTime.now().millisecondsSinceEpoch; final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv); final formData = FormData.fromMap({ 'file': files, 'fileType': fileType, 'timestamp': timestamp, 'sign': sign, }); return post( ApiCorePaths.uploadImage, data: formData, domainType: DomainType.file, ); } // 上传多个视频文件 Future uploadMultipleVideoFiles( List filePaths, List fileNames, ) async { final List files = []; for (int i = 0; i < filePaths.length; i++) { final fileData = await MultipartFile.fromFile( filePaths[i], filename: fileNames[i], ); files.add(fileData); } const fileType = 'video'; final timestamp = DateTime.now().millisecondsSinceEpoch; final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv); final formData = FormData.fromMap({ 'file': files, 'fileType': fileType, 'timestamp': timestamp, 'sign': sign, }); return post( ApiCorePaths.uploadVideo, data: formData, domainType: DomainType.file, ); } }