o2_http_client.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. import 'dart:io';
  2. import 'package:dio/dio.dart';
  3. import 'package:get/get_utils/get_utils.dart';
  4. import '../models/index.dart';
  5. import '../widgets/index.dart';
  6. import 'loading.dart';
  7. import 'log_util.dart';
  8. import 'o2_api_manager.dart';
  9. import 'o2_utils.dart';
  10. class O2Interceptor extends Interceptor {
  11. @override
  12. void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
  13. // print("\n================================= 请求数据 =================================");
  14. // print("method = ${options.method.toString()}");
  15. // print("url = ${options.uri.toString()}");
  16. // print("headers = ${options.headers}");
  17. // print("params = ${options.queryParameters}");
  18. super.onRequest(options, handler);
  19. }
  20. @override
  21. void onResponse(Response response, ResponseInterceptorHandler handler) {
  22. // print(
  23. // "\n================================= 响应数据开始 =================================");
  24. // print("code = ${response.statusCode}");
  25. // print("data = ${response.data}");
  26. // print(
  27. // "================================= 响应数据结束 =================================\n");
  28. super.onResponse(response, handler);
  29. }
  30. @override
  31. onError(DioError err, ErrorInterceptorHandler handler) {
  32. try {
  33. var code = err.response?.statusCode;
  34. if (code == 500) {
  35. List<String>? type = err.response?.headers['Content-Type'];
  36. if (type != null &&
  37. (type.contains('application/json') ||
  38. type.contains('application/json;charset=utf-8'))) {
  39. ApiResponse a = ApiResponse.fromJson(err.response?.data);
  40. if (a.message != null && a.message!.isNotEmpty) {
  41. Loading.toast(a.message!);
  42. }
  43. return super.onError(
  44. DioError(
  45. requestOptions: err.requestOptions,
  46. response: err.response,
  47. error: a.message),
  48. handler);
  49. }
  50. } else if (err.response?.statusCode == 401) { // token过期 需要重新登录
  51. OLogger.e('401 异常 ${err.response.toString()}');
  52. O2OverlayEntryDialog.instance.openAlertDialog(
  53. 'error'.tr,
  54. 'common_session_timeout'.tr, callback: () => O2Utils.logout(hasToken: false));
  55. } else {
  56. OLogger.e(err);
  57. }
  58. } catch (e) {
  59. OLogger.e(e);
  60. }
  61. // Loading.toast('request_error'.tr);
  62. return super.onError(err, handler);
  63. }
  64. }
  65. class O2HttpClient {
  66. static final O2HttpClient instance = O2HttpClient._internal();
  67. factory O2HttpClient() {
  68. return instance;
  69. }
  70. O2HttpClient._internal() {
  71. //初始化
  72. _dio = Dio();
  73. _dio.interceptors.add(O2Interceptor());
  74. }
  75. late Dio _dio;
  76. get dio {
  77. return _dio;
  78. }
  79. ///
  80. /// post方法 json
  81. ///
  82. Future<ApiResponse> post(String url, Map<String, dynamic> data,
  83. {bool needToken = true}) async {
  84. Response<dynamic> response =
  85. await _dio.post(url, data: data, options: _postJsonOptions(needToken));
  86. return ApiResponse.fromJson(response.data);
  87. }
  88. ///
  89. /// get方法 json
  90. ///
  91. Future<ApiResponse> get(String url, {bool needToken = true, CancelToken? cancelToken}) async {
  92. Response<dynamic> response =
  93. await _dio.get(url, options: _getJsonOptions(needToken), cancelToken: cancelToken);
  94. return ApiResponse.fromJson(response.data);
  95. }
  96. /// 不转 ApiResponse 对象 外部使用的
  97. Future<Response<dynamic>> getOuter(String url) async {
  98. return await _dio.get(url, options: _getJsonOptions(false));
  99. }
  100. getWithCallback(String url, Function(ApiResponse?, dynamic) callback, {bool needToken = true}) async {
  101. _dio.get(url, options: _getJsonOptions(needToken)).then((response) {
  102. OLogger.d('执行了then');
  103. callback(ApiResponse.fromJson(response.data), null);
  104. }).catchError((e) {
  105. OLogger.d('执行了异常');
  106. callback(null, e);
  107. });
  108. }
  109. ///
  110. /// put 方法 json
  111. ///
  112. Future<ApiResponse> put(String url, Map<String, dynamic> data,
  113. {bool needToken = true, CancelToken? cancelToken}) async {
  114. var mock = _needChange2Mock(url, "put");
  115. if (mock != null) {
  116. var newUrl = "$url/${mock.append}";
  117. var to = mock.to;
  118. if (to != null && to.isNotEmpty) {
  119. if (to.toLowerCase() == 'post') {
  120. // put 方法转 post
  121. Response<dynamic> response = await _dio.post(newUrl,
  122. data: data, options: _putJsonOptions(needToken, newMethod: to));
  123. return ApiResponse.fromJson(response.data);
  124. }
  125. }
  126. }
  127. Response<dynamic> response =
  128. await _dio.put(url, data: data, options: _putJsonOptions(needToken), cancelToken: cancelToken);
  129. return ApiResponse.fromJson(response.data);
  130. }
  131. ///
  132. /// delete方法 json
  133. ///
  134. Future<ApiResponse> delete(String url, {bool needToken = true}) async {
  135. var mock = _needChange2Mock(url, "delete");
  136. if (mock != null) {
  137. var newUrl = "$url/${mock.append}";
  138. var to = mock.to;
  139. if (to != null && to.isNotEmpty) {
  140. if (to.toLowerCase() == 'get') {
  141. // delete 方法转 get
  142. Response<dynamic> response = await _dio.get(newUrl,
  143. options: _deleteJsonOptions(needToken, newMethod: to));
  144. return ApiResponse.fromJson(response.data);
  145. } else if (to.toLowerCase() == 'post') {
  146. // delete 方法转 post
  147. Response<dynamic> response = await _dio.post(newUrl,
  148. data: null,
  149. options: _deleteJsonOptions(needToken, newMethod: to));
  150. return ApiResponse.fromJson(response.data);
  151. }
  152. }
  153. }
  154. Response<dynamic> response =
  155. await _dio.delete(url, options: _deleteJsonOptions(needToken));
  156. return ApiResponse.fromJson(response.data);
  157. }
  158. ///
  159. /// PUT方法上传文件
  160. ///
  161. Future<ApiResponse> putUploadFile(String url, File file,
  162. {Map<String, dynamic>? body, void Function(int, int)? onSendProgress}) async {
  163. var fileName = _filename(file);
  164. Map<String, dynamic> form = {};
  165. if (body != null) {
  166. form = body;
  167. }
  168. form["file"] = await MultipartFile.fromFile(file.path, filename: fileName);
  169. FormData formData = FormData.fromMap(form);
  170. // FormData formData = FormData.fromMap({
  171. // "file": await MultipartFile.fromFile(file.path, filename: fileName),
  172. // });
  173. Response<dynamic> response =
  174. await _dio.put(url, data: formData, options: _putJsonOptions(true), onSendProgress: onSendProgress);
  175. return ApiResponse.fromJson(response.data);
  176. }
  177. ///
  178. /// POST方法上传文件
  179. ///
  180. Future<ApiResponse> postUploadFile(String url, File file,
  181. {Map<String, dynamic>? body, void Function(int, int)? onSendProgress}) async {
  182. var fileName = _filename(file);
  183. Map<String, dynamic> form = {};
  184. if (body != null) {
  185. form = body;
  186. }
  187. form["file"] = await MultipartFile.fromFile(file.path, filename: fileName);
  188. FormData formData = FormData.fromMap(form);
  189. Response<dynamic> response =
  190. await _dio.post(url, data: formData, options: _postJsonOptions(true), onSendProgress: onSendProgress);
  191. return ApiResponse.fromJson(response.data);
  192. }
  193. ///
  194. /// 下载文件
  195. ///
  196. Future<Response> downloadFile(String url, String savePath,
  197. {ProgressCallback? onReceiveProgress}) async {
  198. Map<String, String> header = {};
  199. header['x-client'] = _xClient();
  200. if (O2ApiManager.instance.o2User != null) {
  201. header[O2ApiManager.instance.tokenName] =
  202. O2ApiManager.instance.o2User?.token ?? '';
  203. }
  204. header[HttpHeaders.acceptEncodingHeader] = "*";
  205. Options options = Options(headers: header);
  206. Response response = await _dio.download(url, savePath,
  207. onReceiveProgress: onReceiveProgress, options: options);
  208. return response;
  209. }
  210. ///
  211. /// 下载文件
  212. /// 不知道文件名称的情况
  213. ///
  214. Future<String> downloadFileNoFileName(String url, String saveFolderPath,
  215. {ProgressCallback? onReceiveProgress}) async {
  216. Map<String, String> header = {};
  217. header['x-client'] = _xClient();
  218. if (O2ApiManager.instance.o2User != null) {
  219. header[O2ApiManager.instance.tokenName] =
  220. O2ApiManager.instance.o2User?.token ?? '';
  221. }
  222. header[HttpHeaders.acceptEncodingHeader] = "*";
  223. Options options = Options(headers: header);
  224. String fileLocalPath = '';
  225. await _dio.download(url, (Headers headers) {
  226. var fileName = headers.value("Content-Disposition");
  227. if (fileName != null && fileName.isNotEmpty) {
  228. var i = fileName.lastIndexOf("''");
  229. if (i > -1) {
  230. fileName = fileName.substring(i + "''".length, fileName.length);
  231. }
  232. }
  233. if (fileName == null || fileName.isEmpty == true) {
  234. fileName = 'unknow';
  235. }
  236. fileLocalPath = '$saveFolderPath/$fileName';
  237. return fileLocalPath;
  238. }, onReceiveProgress: onReceiveProgress, options: options);
  239. return fileLocalPath;
  240. }
  241. String _filename(File file) {
  242. if (file.existsSync()) {
  243. var index = file.path.lastIndexOf(Platform.pathSeparator);
  244. return file.path.substring(index + 1, file.path.length);
  245. }
  246. return '';
  247. }
  248. ///
  249. ///是否需要替换方法类型
  250. ///比如 put转post
  251. ///
  252. MockMode? _needChange2Mock(String url, String currentMethod) {
  253. var mock = O2ApiManager.instance.centerServerInfo?.mockConfig?.mock;
  254. MockMode? mm;
  255. if (mock != null) {
  256. for (var element in mock.keys) {
  257. if (url.contains(element)) {
  258. // 判断是需要转化的模块
  259. var mode = mock[element] as Map<String, MockMode>;
  260. for (var method in mode.keys) {
  261. if (currentMethod.toLowerCase() == method.toLowerCase()) {
  262. // 请求方法相同
  263. mm = mode[method];
  264. continue;
  265. }
  266. }
  267. continue;
  268. }
  269. }
  270. }
  271. return mm;
  272. }
  273. Options _deleteJsonOptions(bool needToken, {String? newMethod}) {
  274. Map<String, String> header = <String, String>{};
  275. header['x-client'] = _xClient();
  276. if (needToken && O2ApiManager.instance.o2User != null) {
  277. header[O2ApiManager.instance.tokenName] =
  278. O2ApiManager.instance.o2User?.token ?? '';
  279. }
  280. return Options(
  281. method: newMethod == null || newMethod.isEmpty ? 'DELETE' : newMethod,
  282. headers: header,
  283. contentType: ContentType.json.mimeType);
  284. }
  285. Options _getJsonOptions(bool needToken) {
  286. Map<String, String> header = <String, String>{};
  287. header['x-client'] = _xClient();
  288. if (needToken && O2ApiManager.instance.o2User != null) {
  289. header[O2ApiManager.instance.tokenName] =
  290. O2ApiManager.instance.o2User?.token ?? '';
  291. }
  292. return Options(
  293. method: 'GET', headers: header, contentType: ContentType.json.mimeType);
  294. }
  295. Options _postJsonOptions(bool needToken) {
  296. Map<String, String> header = <String, String>{};
  297. header['x-client'] = _xClient();
  298. if (needToken && O2ApiManager.instance.o2User != null) {
  299. header[O2ApiManager.instance.tokenName] =
  300. O2ApiManager.instance.o2User?.token ?? '';
  301. }
  302. return Options(
  303. method: 'POST',
  304. headers: header,
  305. contentType: ContentType.json.mimeType);
  306. }
  307. Options _putJsonOptions(bool needToken, {String? newMethod}) {
  308. Map<String, String> header = <String, String>{};
  309. header['x-client'] = _xClient();
  310. if (needToken && O2ApiManager.instance.o2User != null) {
  311. header[O2ApiManager.instance.tokenName] =
  312. O2ApiManager.instance.o2User?.token ?? '';
  313. }
  314. return Options(
  315. method: newMethod == null || newMethod.isEmpty ? 'PUT' : newMethod,
  316. headers: header,
  317. contentType: ContentType.json.mimeType);
  318. }
  319. String _xClient() {
  320. String xClient = "flutter";
  321. if (Platform.isAndroid) {
  322. xClient = 'android';
  323. } else if (Platform.isIOS) {
  324. xClient = 'ios';
  325. }
  326. return xClient;
  327. }
  328. }