api_file.dart 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import 'dart:convert';
  2. import 'package:archive/archive.dart';
  3. import 'package:dio/dio.dart';
  4. import 'package:uuid/uuid.dart';
  5. import '../../../utils/crypto.dart';
  6. import '../../../utils/developer/ix_developer_tools.dart';
  7. import '../../../utils/log/logger.dart';
  8. import '../../constants/keys.dart';
  9. import '../../data/models/api_exception.dart';
  10. import '../../data/models/api_result.dart';
  11. import '../../data/models/disconnect_domain.dart';
  12. import '../../data/sp/ix_sp.dart';
  13. import '../base/base_api.dart';
  14. import '../core/api_core_paths.dart';
  15. /// 核心API
  16. class ApiFile extends BaseApi {
  17. static final _instance = ApiFile._internal();
  18. factory ApiFile() => _instance;
  19. ApiFile._internal() {
  20. _initDio();
  21. }
  22. /// 初始化Dio
  23. void _initDio() {
  24. // 此处可以设置默认的DIO参数
  25. final options = BaseOptions();
  26. options.connectTimeout = const Duration(seconds: 90);
  27. options.receiveTimeout = const Duration(seconds: 90);
  28. options.responseType = ResponseType.bytes;
  29. options.headers['content-type'] = 'multipart/form-data';
  30. dio = Dio(options);
  31. // 添加talker日志
  32. dio.interceptors.add(SimpleApiMonitorInterceptor());
  33. // 添加拦截器
  34. _setupInterceptors();
  35. }
  36. // bool _isRefreshing = false;
  37. void _setupInterceptors() {
  38. dio.interceptors.add(
  39. InterceptorsWrapper(
  40. onRequest: (options, handler) async {
  41. // 在请求发送前添加token
  42. final user = IXSP.getUser();
  43. if (user != null) {
  44. options.headers['Authorization'] = user.accessToken;
  45. }
  46. return handler.next(options);
  47. },
  48. onError: (DioException error, handler) async {
  49. IXSP.addDisconnectDomain(
  50. DisconnectDomain(
  51. domain: error.requestOptions.baseUrl,
  52. status: error.response?.statusCode ?? -1,
  53. msg: error.message ?? '',
  54. startTime: DateTime.now().millisecondsSinceEpoch,
  55. endTime: DateTime.now().millisecondsSinceEpoch,
  56. count: 1,
  57. ),
  58. );
  59. return handler.next(error);
  60. },
  61. ),
  62. );
  63. }
  64. @override
  65. Map<String, dynamic>? getDefaultHeader() {
  66. // 可以设置自定义Header
  67. final headers = {
  68. 'X-NL-Product-Code': 'nomo',
  69. 'X-NL-Content-Encoding': 'gzip',
  70. };
  71. return headers;
  72. }
  73. @override
  74. Map<String, dynamic>? getDefaultQuery() {
  75. // 可以设置自定义Query
  76. return null;
  77. }
  78. @override
  79. dynamic encrypt(dynamic input) {
  80. return input;
  81. }
  82. @override
  83. dynamic decrypt(dynamic input) {
  84. try {
  85. final decryptedBytes = Crypto.decryptBytes(
  86. base64Encode(input),
  87. Keys.aesKey,
  88. Keys.aesIv,
  89. );
  90. // 使用GZip解压
  91. final gzipDecoder = GZipDecoder();
  92. final decodeBytes = gzipDecoder.decodeBytes(decryptedBytes);
  93. final data = utf8.decode(decodeBytes);
  94. log('ApiCore', '<<:$data');
  95. return jsonDecode(data);
  96. } catch (error) {
  97. throw ApiException("-2", "decrypt error: $error");
  98. }
  99. }
  100. // 上传日志文件
  101. Future<ApiResult> uploadLogFile(
  102. String filePath,
  103. String fileName,
  104. String logType,
  105. String data,
  106. ) async {
  107. final fileData = await MultipartFile.fromFile(filePath, filename: fileName);
  108. const fileType = 'gzip';
  109. final timestamp = DateTime.now().millisecondsSinceEpoch;
  110. final sign = Crypto.encrypt(
  111. '$fileType$logType$timestamp',
  112. Keys.aesKey,
  113. Keys.aesIv,
  114. );
  115. if (logType == "App_NL_Log") {
  116. final logId = const Uuid().v4();
  117. final userInfo = Crypto.encrypt(data, Keys.aesKey, Keys.aesIv);
  118. final formData = FormData.fromMap({
  119. 'file': fileData,
  120. 'fileName': fileName,
  121. 'fileType': fileType,
  122. 'logType': logType,
  123. 'timestamp': timestamp,
  124. 'sign': sign,
  125. 'userInfo': userInfo,
  126. 'logId': logId,
  127. });
  128. return post(
  129. ApiCorePaths.uploadFile,
  130. data: formData,
  131. domainType: DomainType.file,
  132. );
  133. } else {
  134. final formData = FormData.fromMap({
  135. 'file': fileData,
  136. 'fileName': fileName,
  137. 'fileType': fileType,
  138. 'timestamp': timestamp,
  139. 'logType': logType,
  140. 'sign': sign,
  141. });
  142. return post(
  143. ApiCorePaths.uploadFile,
  144. data: formData,
  145. domainType: DomainType.file,
  146. );
  147. }
  148. }
  149. // 上传图片文件
  150. Future<ApiResult> uploadImageFile(String filePath, String fileName) async {
  151. final fileData = await MultipartFile.fromFile(filePath, filename: fileName);
  152. const fileType = 'image';
  153. final timestamp = DateTime.now().millisecondsSinceEpoch;
  154. final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv);
  155. final formData = FormData.fromMap({
  156. 'file': fileData,
  157. 'fileType': fileType,
  158. 'timestamp': timestamp,
  159. 'sign': sign,
  160. });
  161. return post(
  162. ApiCorePaths.uploadImage,
  163. data: formData,
  164. domainType: DomainType.file,
  165. );
  166. }
  167. // 上传视频文件
  168. Future<ApiResult> uploadVideoFile(String filePath, String fileName) async {
  169. final fileData = await MultipartFile.fromFile(filePath, filename: fileName);
  170. const fileType = 'video';
  171. final timestamp = DateTime.now().millisecondsSinceEpoch;
  172. final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv);
  173. final formData = FormData.fromMap({
  174. 'file': fileData,
  175. 'fileType': fileType,
  176. 'timestamp': timestamp,
  177. 'sign': sign,
  178. });
  179. return post(
  180. ApiCorePaths.uploadVideo,
  181. data: formData,
  182. domainType: DomainType.file,
  183. );
  184. }
  185. // 上传多个图片文件
  186. Future<ApiResult> uploadMultipleImageFiles(
  187. List<String> filePaths,
  188. List<String> fileNames,
  189. ) async {
  190. final List<MultipartFile> files = [];
  191. for (int i = 0; i < filePaths.length; i++) {
  192. final fileData = await MultipartFile.fromFile(
  193. filePaths[i],
  194. filename: fileNames[i],
  195. );
  196. files.add(fileData);
  197. }
  198. const fileType = 'image';
  199. final timestamp = DateTime.now().millisecondsSinceEpoch;
  200. final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv);
  201. final formData = FormData.fromMap({
  202. 'file': files,
  203. 'fileType': fileType,
  204. 'timestamp': timestamp,
  205. 'sign': sign,
  206. });
  207. return post(
  208. ApiCorePaths.uploadImage,
  209. data: formData,
  210. domainType: DomainType.file,
  211. );
  212. }
  213. // 上传多个视频文件
  214. Future<ApiResult> uploadMultipleVideoFiles(
  215. List<String> filePaths,
  216. List<String> fileNames,
  217. ) async {
  218. final List<MultipartFile> files = [];
  219. for (int i = 0; i < filePaths.length; i++) {
  220. final fileData = await MultipartFile.fromFile(
  221. filePaths[i],
  222. filename: fileNames[i],
  223. );
  224. files.add(fileData);
  225. }
  226. const fileType = 'video';
  227. final timestamp = DateTime.now().millisecondsSinceEpoch;
  228. final sign = Crypto.encrypt('$fileType$timestamp', Keys.aesKey, Keys.aesIv);
  229. final formData = FormData.fromMap({
  230. 'file': files,
  231. 'fileType': fileType,
  232. 'timestamp': timestamp,
  233. 'sign': sign,
  234. });
  235. return post(
  236. ApiCorePaths.uploadVideo,
  237. data: formData,
  238. domainType: DomainType.file,
  239. );
  240. }
  241. }