UploadController.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { set } from "lodash";
  2. import loading from "@/components/Provider/Loading";
  3. import { message } from "ant-design-vue";
  4. export class UploadController {
  5. request: any;
  6. blobURLMaps = new Map<string, any>();
  7. constructor(request: any) {
  8. this.request = request;
  9. }
  10. getBlobURLName(url: string) {
  11. return this.blobURLMaps.get(url)?.name;
  12. }
  13. createObjectURL(obj: Blob): string {
  14. const url = URL.createObjectURL(obj);
  15. this.blobURLMaps.set(url, obj);
  16. return url;
  17. }
  18. revokeObjectURL(url: string) {
  19. URL.revokeObjectURL(url);
  20. this.blobURLMaps.delete(url);
  21. }
  22. selectFile(opts?: { accept?: string; multiple?: boolean }): Promise<File[]> {
  23. return new Promise((resolve, reject) => {
  24. const fileInput = document.createElement("input");
  25. fileInput.type = "file";
  26. fileInput.accept = opts?.accept || "images/*";
  27. fileInput.multiple = opts?.multiple || false;
  28. fileInput.onchange = function (this: any) {
  29. resolve([...this.files]);
  30. };
  31. window.addEventListener(
  32. "focus",
  33. () => {
  34. setTimeout(() => {
  35. reject(console.warn("select file cancel"));
  36. }, 300);
  37. },
  38. { once: true }
  39. );
  40. fileInput.click();
  41. });
  42. }
  43. async uploadBlobImages(data: object) {
  44. const todoMap = new Map<string, string>();
  45. addBlobToList(data);
  46. const todoList = todoMap.entries();
  47. let err = "";
  48. for (const item of todoList) {
  49. const [blobUrl, path] = item;
  50. const file = this.blobURLMaps.get(blobUrl);
  51. if (file) {
  52. const paths = path.split(",");
  53. loading.show("上传中");
  54. const ret = await this.uploadImage(file);
  55. if (ret.url) {
  56. paths.forEach((p) => {
  57. set(data, p, ret.url);
  58. });
  59. this.revokeObjectURL(blobUrl);
  60. } else {
  61. err = ret.error || `上传文件失败[${path}]`;
  62. break;
  63. }
  64. } else {
  65. err = `上传文件为空[${path}]`;
  66. }
  67. }
  68. loading.hidden();
  69. if (err) {
  70. message.error(err);
  71. throw err;
  72. }
  73. function addBlobToList(data: any, path = "") {
  74. if (data instanceof Object) {
  75. if (data instanceof Array) {
  76. data.forEach((item, i) => {
  77. addBlobToList(item, path ? path + "." + i : i.toString());
  78. });
  79. } else {
  80. Object.entries(data).forEach(([key, value]) => {
  81. addBlobToList(value, path ? path + "." + key : key);
  82. });
  83. }
  84. }
  85. if (typeof data === "string" && /^blob:/.test(data)) {
  86. if (todoMap.has(data)) {
  87. path = todoMap.get(data) + "," + path;
  88. }
  89. todoMap.set(data, path);
  90. }
  91. }
  92. }
  93. async uploadImage(file: File): Promise<{ url?: string; error?: string }> {
  94. const fromData = new FormData();
  95. fromData.append("image", file);
  96. try {
  97. const ret = await this.request("/upload/image", {
  98. method: "POST",
  99. data: fromData,
  100. headers: {
  101. "Content-Type": "multipart/form-data",
  102. },
  103. });
  104. if (ret.errorNo != 200) {
  105. return { error: "上传失败!" };
  106. }
  107. const url = ret.result.url;
  108. return { url };
  109. } catch (e) {
  110. return { error: "上传失败!" };
  111. }
  112. }
  113. async uploadFile(file: File): Promise<{ url?: string; error?: string }> {
  114. const fromData = new FormData();
  115. fromData.append("file", file);
  116. try {
  117. const ret = await this.request("/upload/file", {
  118. method: "POST",
  119. data: fromData,
  120. headers: {
  121. "Content-Type": "multipart/form-data",
  122. },
  123. });
  124. if (ret.errorNo != 200) {
  125. return { error: "上传失败!" };
  126. }
  127. const url = ret.result.url;
  128. return { url };
  129. } catch (e) {
  130. return { error: "上传失败!" };
  131. }
  132. }
  133. getFileExt(file: File) {
  134. let ext: any = "unkown";
  135. if (file) {
  136. const exp = /^.+\.(.+)$/;
  137. if (file.name && exp.test(file.name)) {
  138. ext = (exp.exec(file.name) as any)[1];
  139. } else if (file.type) {
  140. ext = file.type.split("/").pop();
  141. }
  142. return ext.toLowerCase();
  143. } else {
  144. return ext;
  145. }
  146. }
  147. }