axiosUtils.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /**
  2. * 封装axios的类
  3. * nh 2021.12.23
  4. */
  5. import axios from "axios";
  6. import vueStore from "@/store";
  7. import { logicConfig } from "@/logicConfig";
  8. import { toolUtils } from "@/utils/toolUtils";
  9. import SparkMD5 from 'spark-md5';
  10. var CancelToken = axios.CancelToken;
  11. var cancel;
  12. // 创建axios实例
  13. const axiosservice = axios.create({
  14. timeout: 3000000, // 请求超时时间
  15. cancelToken: new CancelToken(function executor(c) {
  16. // executor 函数接收一个 cancel 函数作为参数
  17. cancel = c;
  18. }),
  19. });
  20. axiosservice.interceptors.request.use(
  21. (config) => {
  22. return config;
  23. },
  24. (error) => {
  25. return Promise.reject(error);
  26. }
  27. );
  28. axiosservice.interceptors.response.use(
  29. function (res) {
  30. //在这里对返回的数据进行处理
  31. let resp = res.data;
  32. return res;
  33. },
  34. function (err) {
  35. console.error("axios interceptors err = ", err);
  36. return Promise.reject(err);
  37. }
  38. );
  39. export class axiosUtils {
  40. /**
  41. * get请求
  42. * @param url
  43. * @param data
  44. * @returns
  45. */
  46. protected async getRequest(url: string, data: any) {
  47. try {
  48. var urlArr = url.split("?");
  49. var urlPrefix = urlArr[0];
  50. var urlParamStr = urlArr[1] || "";
  51. var _newParamStr = toolUtils.objectKeyToUrlParam(data);
  52. var newUrl = urlPrefix + '?' + _newParamStr + '&' + urlParamStr;
  53. let response = await this.customRequest(newUrl, {}, {}, "get");
  54. return response;
  55. } catch (err) {
  56. throw err;
  57. }
  58. }
  59. /**
  60. * post请求
  61. * @param url
  62. * @param data
  63. * @returns
  64. */
  65. protected async postRequest(url: string, data: any) {
  66. try {
  67. let response = await this.customRequest(url, {}, data, "post");
  68. return response;
  69. } catch (err) {
  70. throw err;
  71. }
  72. }
  73. /**
  74. * 自定义请求
  75. * @param url
  76. * @param headers
  77. * @param data
  78. * @param method get | post 默认post
  79. * @returns
  80. */
  81. protected async customRequest(
  82. url: string,
  83. headers: any,
  84. data: any,
  85. method: string = "post"
  86. ) {
  87. try {
  88. //headers里放入 groupCode、projectId 为了兼顾老ADM的写法,以后可删除
  89. headers = headers || {};
  90. headers.groupCode =
  91. headers.groupCode || vueStore.state.selectProject.groupCode;
  92. headers.projectId = headers.projectId || vueStore.state.selectProject.id;
  93. var urlArr = url.split("?");
  94. var urlPrefix = urlArr[0];
  95. var urlParamStr = urlArr[1] || "";
  96. if (urlParamStr.indexOf("projectId=") == -1) {
  97. urlParamStr =
  98. "projectId=" + vueStore.state.selectProject.id + "&" + urlParamStr;
  99. }
  100. if (urlParamStr.indexOf("groupCode=") == -1) {
  101. urlParamStr =
  102. "groupCode=" +
  103. vueStore.state.selectProject.groupCode +
  104. "&" +
  105. urlParamStr;
  106. }
  107. url = urlPrefix + "?" + urlParamStr;
  108. let response = await axiosservice({
  109. url,
  110. headers: headers || {},
  111. data,
  112. method: method == "post" ? "post" : "get",
  113. });
  114. return response.data;
  115. } catch (err) {
  116. // throw err;
  117. console.error(err);
  118. return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '请求异常,' + err.message);
  119. }
  120. }
  121. /**
  122. * 上传文件
  123. * @param _paramobj 格式如下:
  124. * {
  125. * fileServiceUrl 文件服务地址
  126. * uploadProgressCall 上传进度回调函数,函数参数为object,格式如下:{fileName:'文件名称',uploadedTotal:1},uploadedTotal某个文件总共上传的字节数
  127. * oneUploadedCall 每上传完一个后的回调函数,函数参数为object,格式如下:{fileName:'文件名称',fileId:'文件ID'}
  128. * userId:'不传时,默认会取vuex中user.id',
  129. * files 数组或者object,示例
  130. * {
  131. * groupCode:'不传时,默认会取vuex中selectProject.groupCode',
  132. * projectId:'不传时,默认会取vuex中selectProject.id',
  133. * fileName:'文件名称',
  134. * fileBucket:'存储空间名称,可以不传',
  135. * file:文件信息,假设有一个input type为file id为txtFile的标签,那么file为document.getElementById('txtFile').files[0]
  136. * }
  137. * }
  138. * @returns
  139. */
  140. protected async uploadFiles(_paramobj: any) {
  141. //注意,这里的this 指向的是实例化的子类
  142. var _this = this;
  143. let userId = _paramobj.userId || vueStore.state.user.id;
  144. let fileServiceUrl = _paramobj.fileServiceUrl;
  145. let files = _paramobj.files;
  146. try {
  147. let waitFiles = files instanceof Array == true ? files : [files];
  148. //上传成功的文件数量
  149. let uploadedCount = 0;
  150. for (let i = 0; i < waitFiles.length; i++) {
  151. let _currFileObj = waitFiles[i];
  152. //获取文件md5
  153. let fileContentMd5 = await getFileContentMd5(_currFileObj);
  154. //获取文件上传地址
  155. let getUploadResult = await getUploadUrl(fileContentMd5 as string, _currFileObj);
  156. switch (getUploadResult.result) {
  157. case logicConfig.resultObj.success:
  158. let getUploadData = getUploadResult.data || {};
  159. //uploadCode 200 代表已经上传过了; 201 代表需上传
  160. switch (getUploadData.uploadCode) {
  161. case 201:
  162. //获取文件地址上传成功时进行上传
  163. let uploadUrl = ((getUploadData.content || [])[0] || {}).uploadUrl;
  164. if (!uploadUrl)
  165. return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '未获取到文件' + _currFileObj.fileName + '的上传地址');
  166. //开始上传
  167. await upload(uploadUrl, _currFileObj.file, function (progressObj) {
  168. if (typeof _paramobj.uploadProgressCall == 'function') {
  169. let uploadedFileSize = progressObj.loaded / progressObj.total * _currFileObj.file.size;
  170. _paramobj.uploadProgressCall({ uploadedTotal: uploadedFileSize, fileName: _currFileObj.fileName });
  171. }
  172. });
  173. case 200:
  174. ++uploadedCount;
  175. if (typeof _paramobj.oneUploadedCall == 'function') {
  176. _paramobj.oneUploadedCall({ fileName: _currFileObj.fileName, fileId: getUploadData.id });
  177. }
  178. break;
  179. }
  180. break;
  181. default:
  182. return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '获取文件' + _currFileObj.fileName + '的上传地址时出错:' + getUploadResult.message);
  183. }
  184. if (uploadedCount == waitFiles.length)
  185. return toolUtils.resultConstructor(logicConfig.resultObj.success, null, null);
  186. }
  187. } catch (error) {
  188. console.error(error);
  189. return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, error.message);
  190. }
  191. //获取文件内容的md5值
  192. function getFileContentMd5(_fileObj) {
  193. return new Promise((resolve, reject) => {
  194. let file = _fileObj.file;
  195. let blobSlice = File.prototype.slice;
  196. let chunkSize = 2097152;
  197. let chunks = Math.ceil(file.size / chunkSize);
  198. let currentChunk = 0;
  199. let spark = new SparkMD5.ArrayBuffer();
  200. let fileReader = new FileReader();
  201. fileReader.onload = function (e) {
  202. spark.append(e.target.result); // Append array buffer
  203. currentChunk++;
  204. if (currentChunk < chunks) {
  205. loadNext();
  206. } else {
  207. let fileContentMd5 = spark.end();
  208. console.info('computed hash', fileContentMd5); // Compute hash
  209. //文件md5获取完成后,调用后台接口获取上传地址
  210. // let getUploadResult = await getUploadUrl(fileContentMd5, _fileObj.fileName, file.size);
  211. resolve(fileContentMd5);
  212. }
  213. };
  214. fileReader.onerror = function (e) {
  215. let errStr = '文件:' + _fileObj.fileName + '读取错误:';
  216. console.error(e);
  217. reject(errStr);
  218. };
  219. function loadNext() {
  220. var start = currentChunk * chunkSize,
  221. end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
  222. fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
  223. }
  224. loadNext();
  225. });
  226. };
  227. //获取文件上传地址
  228. async function getUploadUrl(fileContentMd5: string, _fileObj: any) {
  229. let fileName = _fileObj.fileName;
  230. let fileSize = _fileObj.file.size;
  231. let projectId = _fileObj.projectId || vueStore.state.selectProject.id;
  232. let groupCode = _fileObj.groupCode || vueStore.state.selectProject.groupCode;
  233. //应用ID暂时用不上
  234. let appId = '';
  235. let getUploadUrl = toolUtils.getBaseHttpUrl(fileServiceUrl, 'file/initSingleUpload') +
  236. '?userId=' + userId + '&projectId=' + projectId + '&groupCode=' + groupCode + '&appId=';
  237. let paramObj = {
  238. fileMd5: fileContentMd5,
  239. fileName: fileName,
  240. fileBucket: (window as any).__systemConf.baseRouteUrl,
  241. fileSize: fileSize
  242. };
  243. return await _this.customRequest(getUploadUrl, null, paramObj, 'post');
  244. };
  245. //上传
  246. async function upload(uploadUrl, file, uploadProgressCall) {
  247. return new Promise((resolve, reject) => {
  248. var formData = new FormData();
  249. formData.append('file', file);
  250. axios.put(uploadUrl, formData, {
  251. onUploadProgress: uploadProgressCall
  252. }).then(function (res) {
  253. resolve(res);
  254. }).catch(function (error) {
  255. reject(error);
  256. });
  257. });
  258. }
  259. };
  260. }