index.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { ElMessage } from "element-plus";
  2. import { module, service } from "/@/cool";
  3. import { uuid } from "/@/cool/utils";
  4. import { pathJoin } from "../utils";
  5. import { useBase } from "/$/base";
  6. import { type AxiosProgressEvent } from "axios";
  7. import type { Upload } from "../types";
  8. import { merge } from "lodash-es";
  9. export function useUpload() {
  10. const { options } = module.get("upload");
  11. const { user } = useBase();
  12. // 上传
  13. async function toUpload(
  14. file: File,
  15. opts: Upload.Options = {}
  16. ): Promise<{
  17. key: string;
  18. url: string;
  19. fileId: string;
  20. }> {
  21. return new Promise(async (resolve, reject) => {
  22. // 合并配置
  23. const { prefixPath, onProgress } = merge(opts, options);
  24. // 文件id
  25. const fileId = uuid("");
  26. try {
  27. // 上传模式、类型
  28. const { mode, type } = await service.base.comm.uploadMode();
  29. // 本地上传
  30. const isLocal = mode == "local";
  31. // 文件名
  32. const fileName = fileId + "_" + file.name;
  33. // Key
  34. let key = isLocal ? fileName : pathJoin(prefixPath!, fileName);
  35. // 多种上传请求
  36. // 上传到云端
  37. async function next({
  38. host,
  39. preview,
  40. data
  41. }: {
  42. host: string;
  43. preview?: string;
  44. data?: any;
  45. }) {
  46. const fd = new FormData();
  47. // key
  48. fd.append("key", key);
  49. // 签名数据
  50. for (const i in data) {
  51. if (!fd.has(i)) {
  52. fd.append(i, data[i]);
  53. }
  54. }
  55. // 文件
  56. fd.append("file", file);
  57. // 上传
  58. await service
  59. .request({
  60. url: host,
  61. method: "POST",
  62. headers: {
  63. "Content-Type": "multipart/form-data",
  64. Authorization: isLocal ? user.token : null
  65. },
  66. timeout: 600000,
  67. data: fd,
  68. onUploadProgress(e: AxiosProgressEvent) {
  69. const progress = e.total
  70. ? Math.floor((e.loaded / e.total) * 100)
  71. : 0;
  72. onProgress?.(progress);
  73. },
  74. proxy: isLocal,
  75. NProgress: false
  76. })
  77. .then((res) => {
  78. key = encodeURIComponent(key);
  79. let url = "";
  80. if (isLocal) {
  81. url = res;
  82. } else {
  83. url = pathJoin(preview || host, key);
  84. }
  85. resolve({
  86. key,
  87. url,
  88. fileId
  89. });
  90. })
  91. .catch((err) => {
  92. ElMessage.error(err.message);
  93. reject(err);
  94. });
  95. }
  96. if (isLocal) {
  97. next({
  98. host: "/admin/base/comm/upload"
  99. });
  100. } else {
  101. service.base.comm
  102. .upload(
  103. type == "aws"
  104. ? {
  105. key
  106. }
  107. : {}
  108. )
  109. .then((res) => {
  110. switch (type) {
  111. // 腾讯
  112. case "cos":
  113. next({
  114. host: res.url,
  115. data: res.credentials
  116. });
  117. break;
  118. // 阿里
  119. case "oss":
  120. next({
  121. host: res.host,
  122. preview: res.publicDomain,
  123. data: {
  124. OSSAccessKeyId: res.OSSAccessKeyId,
  125. policy: res.policy,
  126. signature: res.signature
  127. }
  128. });
  129. break;
  130. // 七牛
  131. case "qiniu":
  132. next({
  133. host: res.uploadUrl,
  134. preview: res.publicDomain,
  135. data: {
  136. token: res.token
  137. }
  138. });
  139. break;
  140. // aws
  141. case "aws":
  142. next({
  143. host: res.url,
  144. data: res.fields
  145. });
  146. break;
  147. }
  148. })
  149. .catch(reject);
  150. }
  151. } catch (err) {
  152. ElMessage.error("文件上传失败");
  153. console.error("[upload]", err);
  154. reject(err);
  155. }
  156. });
  157. }
  158. return {
  159. options,
  160. toUpload
  161. };
  162. }