giime 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/index.css +59 -58
  2. package/es/api/materialApi/cross/getAdFileExist.d.ts +1 -0
  3. package/es/api/materialApi/cross/getAdFileExist.mjs.map +1 -1
  4. package/es/components/src/base/chart/Chart.vue.d.ts +2 -2
  5. package/es/components/src/base/chart/index.d.ts +2 -2
  6. package/es/components/src/base/empty/Empty.vue.d.ts +1 -1
  7. package/es/components/src/base/empty/index.d.ts +3 -3
  8. package/es/components/src/business/loginDialog/LoginDialog.vue2.mjs +7 -8
  9. package/es/components/src/business/loginDialog/LoginDialog.vue2.mjs.map +1 -1
  10. package/es/components/src/business/uploadMaterial/UploadMaterial.vue.d.ts +4 -4
  11. package/es/components/src/business/uploadMaterial/index.d.ts +4 -4
  12. package/es/components/src/business/uploadMaterial/uploadMaterial.d.ts +2 -5
  13. package/es/components/src/business/uploadMaterial/uploadMaterial.mjs.map +1 -1
  14. package/es/components/src/composite/fileComponent/FileComponent.vue.d.ts +1 -1
  15. package/es/components/src/composite/fileComponent/index.d.ts +1 -1
  16. package/es/components/src/composite/importDialog/ImportDialog.vue.d.ts +9 -2
  17. package/es/components/src/composite/importDialog/ImportDialog.vue2.mjs +5 -4
  18. package/es/components/src/composite/importDialog/ImportDialog.vue2.mjs.map +1 -1
  19. package/es/components/src/composite/importDialog/index.d.ts +193 -49
  20. package/es/components/src/composite/previewFile/PreviewFile.vue.d.ts +1 -1
  21. package/es/components/src/composite/previewFile/index.d.ts +1 -1
  22. package/es/components/src/composite/uploadFile/UploadFile.vue.d.ts +5 -5
  23. package/es/components/src/composite/uploadFile/UploadFile.vue.mjs +1 -1
  24. package/es/components/src/composite/uploadFile/UploadFile.vue2.mjs +156 -145
  25. package/es/components/src/composite/uploadFile/UploadFile.vue2.mjs.map +1 -1
  26. package/es/components/src/composite/uploadFile/index.d.ts +12 -12
  27. package/es/giime/index.mjs +2 -1
  28. package/es/giime/index.mjs.map +1 -1
  29. package/es/giime/version.d.ts +1 -1
  30. package/es/giime/version.mjs +1 -1
  31. package/es/giime/version.mjs.map +1 -1
  32. package/es/hooks/base/usePasteFile/index.d.ts +89 -0
  33. package/es/hooks/base/usePasteFile/index.mjs +109 -0
  34. package/es/hooks/base/usePasteFile/index.mjs.map +1 -0
  35. package/es/hooks/store/useOrgUserList/index.d.ts +3 -3
  36. package/es/hooks/store/useOrgUserList/index.mjs +3 -3
  37. package/es/hooks/store/useOrgUserList/index.mjs.map +1 -1
  38. package/es/index.css +59 -58
  39. package/es/utils/index.d.ts +1 -0
  40. package/es/utils/index.mjs +2 -1
  41. package/es/utils/index.mjs.map +1 -1
  42. package/es/utils/src/alioss/aliossPutHook.d.ts +116 -41
  43. package/es/utils/src/alioss/aliossPutHook.mjs +165 -97
  44. package/es/utils/src/alioss/aliossPutHook.mjs.map +1 -1
  45. package/es/utils/src/file.d.ts +7 -0
  46. package/es/utils/src/file.mjs +39 -1
  47. package/es/utils/src/file.mjs.map +1 -1
  48. package/es/utils/src/pasteFile/index.d.ts +33 -0
  49. package/es/utils/src/pasteFile/index.mjs +142 -0
  50. package/es/utils/src/pasteFile/index.mjs.map +1 -0
  51. package/lib/api/materialApi/cross/getAdFileExist.d.ts +1 -0
  52. package/lib/api/materialApi/cross/getAdFileExist.js.map +1 -1
  53. package/lib/components/src/base/chart/Chart.vue.d.ts +2 -2
  54. package/lib/components/src/base/chart/index.d.ts +2 -2
  55. package/lib/components/src/base/empty/Empty.vue.d.ts +1 -1
  56. package/lib/components/src/base/empty/index.d.ts +3 -3
  57. package/lib/components/src/business/loginDialog/LoginDialog.vue2.js +7 -8
  58. package/lib/components/src/business/loginDialog/LoginDialog.vue2.js.map +1 -1
  59. package/lib/components/src/business/uploadMaterial/UploadMaterial.vue.d.ts +4 -4
  60. package/lib/components/src/business/uploadMaterial/index.d.ts +4 -4
  61. package/lib/components/src/business/uploadMaterial/uploadMaterial.d.ts +2 -5
  62. package/lib/components/src/business/uploadMaterial/uploadMaterial.js.map +1 -1
  63. package/lib/components/src/composite/fileComponent/FileComponent.vue.d.ts +1 -1
  64. package/lib/components/src/composite/fileComponent/index.d.ts +1 -1
  65. package/lib/components/src/composite/importDialog/ImportDialog.vue.d.ts +9 -2
  66. package/lib/components/src/composite/importDialog/ImportDialog.vue2.js +4 -3
  67. package/lib/components/src/composite/importDialog/ImportDialog.vue2.js.map +1 -1
  68. package/lib/components/src/composite/importDialog/index.d.ts +193 -49
  69. package/lib/components/src/composite/previewFile/PreviewFile.vue.d.ts +1 -1
  70. package/lib/components/src/composite/previewFile/index.d.ts +1 -1
  71. package/lib/components/src/composite/uploadFile/UploadFile.vue.d.ts +5 -5
  72. package/lib/components/src/composite/uploadFile/UploadFile.vue.js +1 -1
  73. package/lib/components/src/composite/uploadFile/UploadFile.vue2.js +160 -149
  74. package/lib/components/src/composite/uploadFile/UploadFile.vue2.js.map +1 -1
  75. package/lib/components/src/composite/uploadFile/index.d.ts +12 -12
  76. package/lib/giime/index.js +334 -328
  77. package/lib/giime/index.js.map +1 -1
  78. package/lib/giime/version.d.ts +1 -1
  79. package/lib/giime/version.js +1 -1
  80. package/lib/giime/version.js.map +1 -1
  81. package/lib/hooks/base/usePasteFile/index.d.ts +89 -0
  82. package/lib/hooks/base/usePasteFile/index.js +111 -0
  83. package/lib/hooks/base/usePasteFile/index.js.map +1 -0
  84. package/lib/hooks/store/useOrgUserList/index.d.ts +3 -3
  85. package/lib/hooks/store/useOrgUserList/index.js +3 -3
  86. package/lib/hooks/store/useOrgUserList/index.js.map +1 -1
  87. package/lib/index.css +59 -58
  88. package/lib/utils/index.d.ts +1 -0
  89. package/lib/utils/index.js +6 -0
  90. package/lib/utils/index.js.map +1 -1
  91. package/lib/utils/src/alioss/aliossPutHook.d.ts +116 -41
  92. package/lib/utils/src/alioss/aliossPutHook.js +165 -97
  93. package/lib/utils/src/alioss/aliossPutHook.js.map +1 -1
  94. package/lib/utils/src/file.d.ts +7 -0
  95. package/lib/utils/src/file.js +40 -0
  96. package/lib/utils/src/file.js.map +1 -1
  97. package/lib/utils/src/pasteFile/index.d.ts +33 -0
  98. package/lib/utils/src/pasteFile/index.js +146 -0
  99. package/lib/utils/src/pasteFile/index.js.map +1 -0
  100. package/package.json +1 -1
@@ -1,73 +1,61 @@
1
1
  import { defineStore } from 'pinia';
2
2
  import { createEventHook } from '@vueuse/core';
3
- import { md5 } from 'js-md5';
4
3
  import AliOss from 'ali-oss';
5
4
  import '../../../api/materialApi/index.mjs';
5
+ import { fileMd5 } from '../file.mjs';
6
6
  import useAliossTokenStore from './aliossToken.mjs';
7
7
  import { getAdFileExist } from '../../../api/materialApi/cross/getAdFileExist.mjs';
8
8
  import { postSaveFileResources } from '../../../api/materialApi/cross/postSaveFileResources.mjs';
9
9
 
10
- const ts_md5_file = (file) => {
11
- return new Promise((resolve) => {
12
- const reader = new FileReader();
13
- reader.onload = async function(e) {
14
- const binary = e.target.result;
15
- resolve(md5(binary));
16
- };
17
- reader.readAsArrayBuffer(file);
18
- });
19
- };
10
+ class AliOssError extends Error {
11
+ constructor(message, code, originalError) {
12
+ super(message);
13
+ this.code = code;
14
+ this.originalError = originalError;
15
+ this.name = "AliOssError";
16
+ }
17
+ }
20
18
  const getParallelPartSize = (size) => {
21
19
  const thresholds = [
22
- {
23
- max: 5,
24
- parallel: 1,
25
- multiplier: 5
26
- },
27
- {
28
- max: 10,
29
- parallel: 2,
30
- multiplier: 4
31
- },
32
- {
33
- max: 30,
34
- parallel: 4,
35
- multiplier: 5
36
- },
37
- {
38
- max: 50,
39
- parallel: 6,
40
- multiplier: 6
41
- },
42
- {
43
- max: Number.POSITIVE_INFINITY,
44
- parallel: 8,
45
- multiplier: 8
46
- }
20
+ { max: 5, parallel: 1, multiplier: 5 },
21
+ // 小于5MB: 单线程,5MB分片
22
+ { max: 10, parallel: 2, multiplier: 4 },
23
+ // 5-10MB: 2线程,4MB分片
24
+ { max: 30, parallel: 4, multiplier: 5 },
25
+ // 10-30MB: 4线程,5MB分片
26
+ { max: 50, parallel: 6, multiplier: 6 },
27
+ // 30-50MB: 6线程,6MB分片
28
+ { max: Number.POSITIVE_INFINITY, parallel: 8, multiplier: 8 }
29
+ // >50MB: 8线程,8MB分片
47
30
  ];
48
31
  const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];
49
32
  return {
50
33
  parallel,
51
34
  partSize: multiplier * 1024 * 1024
35
+ // 转换为字节
52
36
  };
53
37
  };
38
+ const getFileExtension = (filename) => {
39
+ const match = filename.match(/\.(\w+)$/i);
40
+ return match ? match[0] : "";
41
+ };
42
+ const getFileBaseName = (filename) => {
43
+ const ext = getFileExtension(filename);
44
+ return ext ? filename.slice(0, filename.length - ext.length) : filename;
45
+ };
54
46
  const useAliossHookStore = defineStore("aliossHook", () => {
55
47
  const aliossResult = createEventHook();
56
48
  const aliossError = createEventHook();
49
+ const aliossProgress = createEventHook();
57
50
  const saveFileResult = createEventHook();
58
51
  const saveFileError = createEventHook();
59
- const getFileExist = async ({
60
- md5Code,
61
- ext,
62
- name,
63
- size,
64
- uid,
65
- lastModified
66
- }) => {
67
- return new Promise(async (resolve) => {
52
+ const uploadTasks = /* @__PURE__ */ new Map();
53
+ const checkFileExists = async (params) => {
54
+ const { md5Code, ext, name, size, uid, lastModified } = params;
55
+ try {
68
56
  const { data } = await getAdFileExist({ md5Code, ext });
69
57
  if (data.code !== 0 || data.data.count === 0) {
70
- return resolve(false);
58
+ return false;
71
59
  }
72
60
  const result = {
73
61
  name,
@@ -77,104 +65,184 @@ const useAliossHookStore = defineStore("aliossHook", () => {
77
65
  url: data.data.url,
78
66
  md5: md5Code,
79
67
  type: ext,
80
- isExist: true
68
+ isExist: true,
69
+ existId: data.data.id ?? data.data.count
81
70
  };
82
- resolve(result);
83
71
  aliossResult.trigger(result);
84
- });
72
+ return result;
73
+ } catch (error) {
74
+ const err = new AliOssError(`\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u5B58\u5728\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`, "CHECK_FILE_EXIST_ERROR", error);
75
+ aliossError.trigger(err);
76
+ throw err;
77
+ }
85
78
  };
86
- const uploadFile = async ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }) => {
87
- let { name, uid, lastModified, size } = file;
88
- const ext = name.match(/\.(\w+)$/)?.[0] || "";
89
- name = (fileName || name).slice(0, name.lastIndexOf("."));
90
- const md5Code = await ts_md5_file(file);
91
- const FileName = name + ext;
92
- const type = ext.replaceAll(".", "");
79
+ const uploadFile = async (params) => {
80
+ const {
81
+ file,
82
+ fileName,
83
+ folder = "material",
84
+ seat = "default",
85
+ parallel,
86
+ partSize,
87
+ options = {},
88
+ bucket = "giikin-material",
89
+ cdn = "https://sucai.giikin.cn/",
90
+ saveStore = false,
91
+ onProgress,
92
+ abortSignal
93
+ } = params;
94
+ const { name: originalName, uid, lastModified, size } = file;
95
+ const ext = getFileExtension(originalName);
96
+ const baseName = getFileBaseName(fileName || originalName);
97
+ const finalFileName = baseName + ext;
98
+ const fileType = ext.replace(".", "");
93
99
  try {
94
- let result = await getFileExist({ md5Code, ext: type, name: FileName, size, uid, lastModified });
95
- if (result)
96
- return result;
97
- const timestr = Date.now();
98
- const path = `${folder ?? "material"}/${seat ?? "default"}/file-${timestr}-${md5Code}${ext}`;
99
- const P = getParallelPartSize(size);
100
- options = {
101
- ...P,
102
- ...{ parallel, partSize },
103
- ContentDisposition: `attachment;filename=${encodeURIComponent(name)}${ext};filename*=${encodeURIComponent(name)}${ext}`,
100
+ const md5Code = await fileMd5(file);
101
+ const existingFile = await checkFileExists({
102
+ md5Code,
103
+ ext: fileType,
104
+ name: finalFileName,
105
+ size,
106
+ uid,
107
+ lastModified
108
+ });
109
+ if (existingFile) {
110
+ return existingFile;
111
+ }
112
+ if (abortSignal?.aborted) {
113
+ throw new AliOssError("\u4E0A\u4F20\u5DF2\u53D6\u6D88", "UPLOAD_ABORTED");
114
+ }
115
+ const timestamp = Date.now();
116
+ const path = `${folder}/${seat}/file-${timestamp}-${md5Code}${ext}`;
117
+ const sizeInMB = size / (1024 * 1024);
118
+ const uploadParams = getParallelPartSize(sizeInMB);
119
+ const uploadOptions = {
120
+ ...uploadParams,
121
+ ...parallel !== void 0 ? { parallel } : {},
122
+ ...partSize !== void 0 ? { partSize } : {},
123
+ ContentDisposition: `attachment;filename=${encodeURIComponent(baseName)}${ext};filename*=${encodeURIComponent(baseName)}${ext}`,
104
124
  ...options
105
125
  };
106
- const bucketName = bucket || "giikin-material";
107
126
  const { AccessKeyId, AccessKeySecret, SecurityToken } = await useAliossTokenStore().getAliossTokenAsync({
108
- config_id: bucketName
127
+ config_id: bucket
109
128
  });
110
129
  const client = new AliOss({
111
- // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
112
130
  region: "oss-cn-shenzhen",
113
- // 从STS服务获取的临时访问密钥(AccessKey ID、AccessKey Secret、StsToken)。
114
131
  accessKeyId: AccessKeyId,
115
132
  accessKeySecret: AccessKeySecret,
116
133
  stsToken: SecurityToken,
117
- // 刷新临时访问凭证的时间间隔,单位为毫秒。
118
134
  refreshSTSTokenInterval: 3e5,
119
- // 填写Bucket名称。
120
- bucket: bucketName
135
+ bucket
121
136
  });
122
- const upload = options.parallel === 1 ? "put" : "multipartUpload";
123
- const { res } = await client[upload](path, file, options);
124
- if (res.status !== 200) {
125
- aliossError.trigger(res);
126
- return res;
137
+ const uploadMethod = uploadOptions.parallel === 1 ? "put" : "multipartUpload";
138
+ const progressCallback = onProgress ? (p) => {
139
+ onProgress(p);
140
+ aliossProgress.trigger({ file, progress: p });
141
+ } : void 0;
142
+ if (uploadMethod === "multipartUpload") {
143
+ try {
144
+ const uploadOptions2 = { ...uploadOptions };
145
+ if (progressCallback) {
146
+ uploadOptions2.progress = progressCallback;
147
+ }
148
+ const uploadPromise = client.multipartUpload(path, file, uploadOptions2);
149
+ const cancelFn = () => {
150
+ console.warn("\u5C1D\u8BD5\u53D6\u6D88\u4E0A\u4F20\uFF0C\u4F46ali-oss SDK\u53EF\u80FD\u4E0D\u652F\u6301\u53D6\u6D88\u64CD\u4F5C");
151
+ };
152
+ uploadTasks.set(uid, { cancel: cancelFn });
153
+ if (abortSignal) {
154
+ abortSignal.addEventListener("abort", () => {
155
+ cancelFn();
156
+ });
157
+ }
158
+ const result2 = await uploadPromise;
159
+ uploadTasks.delete(uid);
160
+ if (!result2 || !result2.res || result2.res.status !== 200) {
161
+ throw new AliOssError(`\u4E0A\u4F20\u5931\u8D25: ${result2?.res ? `HTTP\u72B6\u6001\u7801 ${result2.res.status}` : "\u672A\u77E5\u9519\u8BEF"}`, "UPLOAD_FAILED", result2);
162
+ }
163
+ } catch (err) {
164
+ uploadTasks.delete(uid);
165
+ throw err;
166
+ }
167
+ } else {
168
+ const result2 = await client.put(path, file, uploadOptions);
169
+ if (!result2 || !result2.res || result2.res.status !== 200) {
170
+ throw new AliOssError(`\u4E0A\u4F20\u5931\u8D25: ${result2?.res ? `HTTP\u72B6\u6001\u7801 ${result2.res.status}` : "\u672A\u77E5\u9519\u8BEF"}`, "UPLOAD_FAILED", result2);
171
+ }
127
172
  }
128
- cdn = cdn ?? "https://sucai.giikin.cn/";
129
173
  const resultUrl = cdn + path;
130
- result = {
174
+ const result = {
131
175
  url: resultUrl,
132
- name: name + ext,
176
+ name: finalFileName,
133
177
  md5: md5Code,
134
- type: ext.replaceAll(".", ""),
178
+ type: fileType,
135
179
  uid,
136
180
  lastModified,
137
181
  size,
138
182
  isExist: false
139
183
  };
140
184
  if (saveStore) {
141
- postSaveFile({ url: resultUrl, md5_code: md5Code, file_size: size });
185
+ saveFileToStore(result).catch((error) => {
186
+ console.error("\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25:", error);
187
+ });
142
188
  }
143
189
  aliossResult.trigger(result);
144
190
  return result;
145
191
  } catch (error) {
146
- aliossError.trigger(error);
147
- return error;
192
+ uploadTasks.delete(uid);
193
+ const err = error instanceof AliOssError ? error : new AliOssError(`\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`, "UPLOAD_ERROR", error);
194
+ aliossError.trigger(err);
195
+ throw err;
148
196
  }
149
197
  };
150
- const postSaveFile = async ({ url, md5_code, file_size }) => {
198
+ const saveFileToStore = async (params) => {
151
199
  try {
200
+ const { url, md5: md5_code, size: file_size } = params;
152
201
  const { data } = await postSaveFileResources({ fileData: { url, md5_code, file_size } });
153
202
  if (data?.code !== 0) {
154
- saveFileError.trigger(data);
155
- return data;
203
+ const errorMsg = data?.comment || data?.data?.message || "\u672A\u77E5\u9519\u8BEF";
204
+ const error = new Error(`\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25: ${errorMsg}`);
205
+ saveFileError.trigger(error);
206
+ throw error;
156
207
  }
157
- const result = {
158
- url,
159
- md5_code,
160
- file_size
161
- };
208
+ const result = { ...params, existId: data.data.id ?? data.comment };
162
209
  saveFileResult.trigger(result);
163
210
  return result;
164
211
  } catch (error) {
165
- saveFileError.trigger(error);
166
- return error;
212
+ const err = error instanceof Error ? error : new Error(`\u4FDD\u5B58\u6587\u4EF6\u5230\u7D20\u6750\u5E93\u5931\u8D25: ${String(error)}`);
213
+ saveFileError.trigger(err);
214
+ throw err;
215
+ }
216
+ };
217
+ const cancelUpload = (uid) => {
218
+ const task = uploadTasks.get(uid);
219
+ if (task) {
220
+ task.cancel();
221
+ uploadTasks.delete(uid);
222
+ return true;
167
223
  }
224
+ return false;
225
+ };
226
+ const cancelAllUploads = () => {
227
+ uploadTasks.forEach((task) => task.cancel());
228
+ uploadTasks.clear();
168
229
  };
169
230
  return {
231
+ // 事件监听器
170
232
  aliossResult: aliossResult.on,
171
233
  aliossError: aliossError.on,
234
+ aliossProgress: aliossProgress.on,
172
235
  saveFileResult: saveFileResult.on,
173
236
  saveFileError: saveFileError.on,
237
+ // 主要方法
174
238
  uploadFile,
175
- postSaveFile
239
+ saveFileToStore,
240
+ cancelUpload,
241
+ cancelAllUploads,
242
+ // 辅助方法
243
+ checkFileExists
176
244
  };
177
245
  });
178
246
 
179
- export { getParallelPartSize, ts_md5_file, useAliossHookStore };
247
+ export { AliOssError, getParallelPartSize, useAliossHookStore };
180
248
  //# sourceMappingURL=aliossPutHook.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"aliossPutHook.mjs","sources":["../../../../../../packages/utils/src/alioss/aliossPutHook.ts"],"sourcesContent":["import { defineStore } from 'pinia';\r\nimport { createEventHook } from '@vueuse/core';\r\nimport { md5 } from 'js-md5';\r\nimport AliOss from 'ali-oss';\r\nimport { type PostSaveFileResourcesData, getAdFileExist, postSaveFileResources } from '@giime/api/materialApi';\r\nimport useAliossTokenStore from './aliossToken';\r\n\r\nexport type PostSaveFileResponse = PostSaveFileResourcesData;\r\nexport type UploadAliOssFile = File & { uid: number };\r\n\r\n/** 上传文件到阿里云 */\r\nexport type AliOssParams = {\r\n /** 资源文件 */\r\n file: UploadAliOssFile;\r\n /** 文件名 */\r\n fileName?: string;\r\n /** 文件存储路径 */\r\n folder?: string;\r\n /** 文件存储位置 */\r\n seat?: string;\r\n /** 并行上传数量 */\r\n parallel?: number;\r\n /** 并行分片大小 */\r\n partSize?: number;\r\n /** 阿里上传配置 */\r\n options?: { [key: string]: any };\r\n /** 阿里服务器 Bucket 名称 */\r\n bucket?: string;\r\n /** cdn */\r\n cdn?: string;\r\n /** 文件是否保存入库 */\r\n saveStore?: boolean;\r\n};\r\n\r\n/** 返回数据 */\r\nexport type AliOssResponse = {\r\n /** 文件地址 */\r\n url: string;\r\n /** 文件名 */\r\n name: string;\r\n /** 文件唯一标识 */\r\n uid: number;\r\n /** 文件最后修改时间 */\r\n lastModified: number;\r\n /** 文件md5 */\r\n md5: string;\r\n /** 文件大小 */\r\n size: number;\r\n /** 文件后缀 */\r\n type: string;\r\n /** 文件库是否存在 */\r\n isExist: boolean;\r\n};\r\n\r\nexport const ts_md5_file = (file: File) => {\r\n return new Promise<string>(resolve => {\r\n const reader = new FileReader();\r\n reader.onload = async function (e) {\r\n const binary = (e.target as any).result;\r\n resolve(md5(binary));\r\n };\r\n reader.readAsArrayBuffer(file);\r\n });\r\n};\r\n\r\n/** 文件分片 */\r\nexport const getParallelPartSize = (size: number) => {\r\n const thresholds = [\r\n {\r\n max: 5,\r\n parallel: 1,\r\n multiplier: 5,\r\n },\r\n {\r\n max: 10,\r\n parallel: 2,\r\n multiplier: 4,\r\n },\r\n {\r\n max: 30,\r\n parallel: 4,\r\n multiplier: 5,\r\n },\r\n {\r\n max: 50,\r\n parallel: 6,\r\n multiplier: 6,\r\n },\r\n {\r\n max: Number.POSITIVE_INFINITY,\r\n parallel: 8,\r\n multiplier: 8,\r\n },\r\n ];\r\n const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];\r\n\r\n return {\r\n parallel,\r\n partSize: multiplier * 1024 * 1024,\r\n };\r\n};\r\n\r\n/** 上传 Hook */\r\nexport const useAliossHookStore = defineStore('aliossHook', () => {\r\n const aliossResult = createEventHook<AliOssResponse>();\r\n const aliossError = createEventHook<any>();\r\n const saveFileResult = createEventHook<PostSaveFileResponse>();\r\n const saveFileError = createEventHook<any>();\r\n\r\n /** 检测广告素材是否已存在 */\r\n const getFileExist = async ({\r\n md5Code,\r\n ext,\r\n name,\r\n size,\r\n uid,\r\n lastModified,\r\n }: {\r\n md5Code: string;\r\n ext: string;\r\n name: string;\r\n size: number;\r\n uid: number;\r\n lastModified: number;\r\n }) => {\r\n // eslint-disable-next-line no-async-promise-executor\r\n return new Promise<AliOssResponse | false>(async resolve => {\r\n const { data } = await getAdFileExist({ md5Code, ext });\r\n if (data.code !== 0 || data.data.count === 0) {\r\n return resolve(false);\r\n }\r\n const result = {\r\n name,\r\n uid,\r\n lastModified,\r\n size,\r\n url: data.data.url,\r\n md5: md5Code,\r\n type: ext,\r\n isExist: true,\r\n };\r\n resolve(result);\r\n aliossResult.trigger(result);\r\n });\r\n };\r\n\r\n /** 上传文件 */\r\n const uploadFile = async ({ file, fileName, folder, seat, parallel, partSize, options, bucket, cdn, saveStore }: AliOssParams) => {\r\n let { name, uid, lastModified, size } = file;\r\n const ext = name.match(/\\.(\\w+)$/)?.[0] || '';\r\n name = (fileName || name).slice(0, name.lastIndexOf('.'));\r\n const md5Code = await ts_md5_file(file);\r\n const FileName = name + ext;\r\n const type = ext.replaceAll('.', '');\r\n\r\n try {\r\n let result = await getFileExist({ md5Code, ext: type, name: FileName, size, uid, lastModified });\r\n if (result) return result;\r\n\r\n // 文件存储路径\r\n const timestr = Date.now();\r\n const path = `${folder ?? 'material'}/${seat ?? 'default'}/file-${timestr}-${md5Code}${ext}`;\r\n\r\n const P = getParallelPartSize(size);\r\n options = {\r\n ...P,\r\n ...{ parallel, partSize },\r\n ContentDisposition: `attachment;filename=${encodeURIComponent(name)}${ext};filename*=${encodeURIComponent(name)}${ext}`,\r\n ...options,\r\n };\r\n\r\n // 阿里云临时上传权限\r\n // 使用组件 props 的默认值\r\n const bucketName = bucket || 'giikin-material';\r\n const { AccessKeyId, AccessKeySecret, SecurityToken } = await useAliossTokenStore().getAliossTokenAsync({\r\n config_id: bucketName,\r\n });\r\n\r\n const client = new AliOss({\r\n // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。\r\n region: 'oss-cn-shenzhen',\r\n // 从STS服务获取的临时访问密钥(AccessKey ID、AccessKey Secret、StsToken)。\r\n accessKeyId: AccessKeyId,\r\n accessKeySecret: AccessKeySecret,\r\n stsToken: SecurityToken,\r\n // 刷新临时访问凭证的时间间隔,单位为毫秒。\r\n refreshSTSTokenInterval: 300000,\r\n // 填写Bucket名称。\r\n bucket: bucketName,\r\n });\r\n\r\n const upload = options.parallel === 1 ? 'put' : 'multipartUpload';\r\n const { res } = await client[upload](path, file, options);\r\n if (res.status !== 200) {\r\n aliossError.trigger(res);\r\n return res;\r\n }\r\n cdn = cdn ?? 'https://sucai.giikin.cn/';\r\n const resultUrl = cdn + path;\r\n result = {\r\n url: resultUrl,\r\n name: name + ext,\r\n md5: md5Code,\r\n type: ext.replaceAll('.', ''),\r\n uid,\r\n lastModified,\r\n size,\r\n isExist: false,\r\n };\r\n if (saveStore) {\r\n postSaveFile({ url: resultUrl, md5_code: md5Code, file_size: size });\r\n }\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n aliossError.trigger(error);\r\n return error;\r\n }\r\n };\r\n\r\n /** 文件入库 */\r\n const postSaveFile = async ({ url, md5_code, file_size }: PostSaveFileResourcesData) => {\r\n try {\r\n const { data } = await postSaveFileResources({ fileData: { url, md5_code, file_size } });\r\n if (data?.code !== 0) {\r\n saveFileError.trigger(data);\r\n return data;\r\n }\r\n const result = {\r\n url,\r\n md5_code,\r\n file_size,\r\n };\r\n saveFileResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n saveFileError.trigger(error);\r\n return error;\r\n }\r\n };\r\n return {\r\n aliossResult: aliossResult.on,\r\n aliossError: aliossError.on,\r\n saveFileResult: saveFileResult.on,\r\n saveFileError: saveFileError.on,\r\n uploadFile,\r\n postSaveFile,\r\n };\r\n});\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aliossPutHook.mjs","sources":["../../../../../../packages/utils/src/alioss/aliossPutHook.ts"],"sourcesContent":["import { defineStore } from 'pinia';\r\nimport { createEventHook } from '@vueuse/core';\r\nimport AliOss from 'ali-oss';\r\nimport { getAdFileExist, postSaveFileResources } from '@giime/api/materialApi';\r\nimport { fileMd5 } from '../file';\r\nimport useAliossTokenStore from './aliossToken';\r\n\r\n/**\r\n * 阿里云OSS上传错误类型\r\n */\r\nexport class AliOssError extends Error {\r\n constructor(\r\n message: string,\r\n public code: string,\r\n public originalError?: unknown,\r\n ) {\r\n super(message);\r\n this.name = 'AliOssError';\r\n }\r\n}\r\n/**\r\n * 上传到阿里云OSS的文件类型\r\n */\r\nexport type UploadAliOssFile = File & { uid: number };\r\n\r\n/**\r\n * 上传进度回调函数类型\r\n */\r\nexport type ProgressCallback = (progress: { percent: number; loaded: number; total: number }) => void;\r\n\r\n/**\r\n * 上传文件到阿里云参数类型\r\n */\r\nexport interface AliOssParams {\r\n /** 资源文件 */\r\n file: UploadAliOssFile;\r\n /** 文件名(可选,默认使用原始文件名) */\r\n fileName?: string;\r\n /** 文件存储路径(可选,默认为'material') */\r\n folder?: string;\r\n /** 文件存储位置(可选,默认为'default') */\r\n seat?: string;\r\n /** 并行上传数量(可选,根据文件大小自动计算) */\r\n parallel?: number;\r\n /** 并行分片大小(可选,根据文件大小自动计算) */\r\n partSize?: number;\r\n /** 阿里上传配置(可选) */\r\n options?: Record<string, any>;\r\n /** 阿里服务器 Bucket 名称(可选,默认为'giikin-material') */\r\n bucket?: string;\r\n /** CDN域名(可选,默认为'https://sucai.giikin.cn/') */\r\n cdn?: string;\r\n /** 文件是否保存入库(可选,默认为false) */\r\n saveStore?: boolean;\r\n /** 上传进度回调(可选) */\r\n onProgress?: ProgressCallback;\r\n /** 取消上传的信号(可选) */\r\n abortSignal?: AbortSignal;\r\n}\r\n\r\n/**\r\n * 阿里云OSS上传响应类型\r\n */\r\nexport interface AliOssResponse {\r\n /** 文件地址 */\r\n url: string;\r\n /** 文件名 */\r\n name: string;\r\n /** 文件唯一标识 */\r\n uid: number;\r\n /** 文件最后修改时间 */\r\n lastModified: number;\r\n /** 文件md5 */\r\n md5: string;\r\n /** 文件大小(字节) */\r\n size: number;\r\n /** 文件后缀(不含点) */\r\n type: string;\r\n /** 文件库是否存在 */\r\n isExist: boolean;\r\n /** 文件库中文件ID */\r\n existId?: number;\r\n}\r\n\r\n/**\r\n * 文件检查参数类型\r\n */\r\ninterface FileExistParams {\r\n md5Code: string;\r\n ext: string;\r\n name: string;\r\n size: number;\r\n uid: number;\r\n lastModified: number;\r\n}\r\n\r\n/**\r\n * 根据文件大小计算并行上传参数\r\n * @param size 文件大小(MB)\r\n * @returns 并行上传参数配置\r\n */\r\nexport const getParallelPartSize = (size: number) => {\r\n // 文件大小阈值(MB)及对应的并行配置\r\n const thresholds = [\r\n { max: 5, parallel: 1, multiplier: 5 }, // 小于5MB: 单线程,5MB分片\r\n { max: 10, parallel: 2, multiplier: 4 }, // 5-10MB: 2线程,4MB分片\r\n { max: 30, parallel: 4, multiplier: 5 }, // 10-30MB: 4线程,5MB分片\r\n { max: 50, parallel: 6, multiplier: 6 }, // 30-50MB: 6线程,6MB分片\r\n { max: Number.POSITIVE_INFINITY, parallel: 8, multiplier: 8 }, // >50MB: 8线程,8MB分片\r\n ];\r\n\r\n // 查找适合当前文件大小的配置\r\n const { parallel, multiplier } = thresholds.find(({ max }) => size <= max) || thresholds[thresholds.length - 1];\r\n\r\n return {\r\n parallel,\r\n partSize: multiplier * 1024 * 1024, // 转换为字节\r\n };\r\n};\r\n\r\n/**\r\n * 从文件名中提取扩展名\r\n * @param filename 文件名\r\n * @returns 扩展名(包含点)\r\n */\r\nconst getFileExtension = (filename: string): string => {\r\n const match = filename.match(/\\.(\\w+)$/i);\r\n return match ? match[0] : '';\r\n};\r\n\r\n/**\r\n * 从文件名中提取基本名称(不含扩展名)\r\n * @param filename 文件名\r\n * @returns 基本名称\r\n */\r\nconst getFileBaseName = (filename: string): string => {\r\n const ext = getFileExtension(filename);\r\n return ext ? filename.slice(0, filename.length - ext.length) : filename;\r\n};\r\n\r\n/**\r\n * 阿里云OSS上传Hook\r\n */\r\nexport const useAliossHookStore = defineStore('aliossHook', () => {\r\n // 创建事件钩子\r\n const aliossResult = createEventHook<AliOssResponse>();\r\n const aliossError = createEventHook<AliOssError | Error>();\r\n const aliossProgress = createEventHook<{ file: UploadAliOssFile; progress: { percent: number; loaded: number; total: number } }>();\r\n const saveFileResult = createEventHook<AliOssResponse>();\r\n const saveFileError = createEventHook<Error>();\r\n\r\n // 存储当前上传任务,用于取消\r\n const uploadTasks = new Map<number, { cancel: () => void }>();\r\n\r\n /**\r\n * 检测文件是否已存在于素材库\r\n * @param params 文件检查参数\r\n * @returns 如果文件存在,返回文件信息;否则返回false\r\n */\r\n const checkFileExists = async (params: FileExistParams): Promise<AliOssResponse | false> => {\r\n const { md5Code, ext, name, size, uid, lastModified } = params;\r\n\r\n try {\r\n const { data } = await getAdFileExist({ md5Code, ext });\r\n\r\n // 文件不存在\r\n if (data.code !== 0 || data.data.count === 0) {\r\n return false;\r\n }\r\n\r\n // 文件已存在,构建响应\r\n const result: AliOssResponse = {\r\n name,\r\n uid,\r\n lastModified,\r\n size,\r\n url: data.data.url,\r\n md5: md5Code,\r\n type: ext,\r\n isExist: true,\r\n existId: data.data.id ?? data.data.count,\r\n };\r\n\r\n // 触发结果事件\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n // 处理错误\r\n const err = new AliOssError(`检查文件是否存在失败: ${error instanceof Error ? error.message : String(error)}`, 'CHECK_FILE_EXIST_ERROR', error);\r\n aliossError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 上传文件到阿里云OSS\r\n * @param params 上传参数\r\n * @returns 上传结果\r\n */\r\n const uploadFile = async (params: AliOssParams): Promise<AliOssResponse> => {\r\n const {\r\n file,\r\n fileName,\r\n folder = 'material',\r\n seat = 'default',\r\n parallel,\r\n partSize,\r\n options = {},\r\n bucket = 'giikin-material',\r\n cdn = 'https://sucai.giikin.cn/',\r\n saveStore = false,\r\n onProgress,\r\n abortSignal,\r\n } = params;\r\n\r\n const { name: originalName, uid, lastModified, size } = file;\r\n\r\n // 提取文件扩展名和基本名称\r\n const ext = getFileExtension(originalName);\r\n const baseName = getFileBaseName(fileName || originalName);\r\n const finalFileName = baseName + ext;\r\n const fileType = ext.replace('.', '');\r\n\r\n try {\r\n // 计算文件MD5\r\n const md5Code = await fileMd5(file);\r\n\r\n // 检查文件是否已存在\r\n const existingFile = await checkFileExists({\r\n md5Code,\r\n ext: fileType,\r\n name: finalFileName,\r\n size,\r\n uid,\r\n lastModified,\r\n });\r\n\r\n // 如果文件已存在,直接返回\r\n if (existingFile) {\r\n return existingFile;\r\n }\r\n\r\n // 如果提供了取消信号并且已经被触发,则取消上传\r\n if (abortSignal?.aborted) {\r\n throw new AliOssError('上传已取消', 'UPLOAD_ABORTED');\r\n }\r\n\r\n // 生成文件存储路径\r\n const timestamp = Date.now();\r\n const path = `${folder}/${seat}/file-${timestamp}-${md5Code}${ext}`;\r\n\r\n // 根据文件大小计算上传参数\r\n const sizeInMB = size / (1024 * 1024);\r\n const uploadParams = getParallelPartSize(sizeInMB);\r\n\r\n // 合并上传选项\r\n const uploadOptions = {\r\n ...uploadParams,\r\n ...(parallel !== undefined ? { parallel } : {}),\r\n ...(partSize !== undefined ? { partSize } : {}),\r\n ContentDisposition: `attachment;filename=${encodeURIComponent(baseName)}${ext};filename*=${encodeURIComponent(baseName)}${ext}`,\r\n ...options,\r\n };\r\n\r\n // 获取阿里云临时上传权限\r\n const { AccessKeyId, AccessKeySecret, SecurityToken } = await useAliossTokenStore().getAliossTokenAsync({\r\n config_id: bucket,\r\n });\r\n\r\n // 创建阿里云OSS客户端\r\n const client = new AliOss({\r\n region: 'oss-cn-shenzhen',\r\n accessKeyId: AccessKeyId,\r\n accessKeySecret: AccessKeySecret,\r\n stsToken: SecurityToken,\r\n refreshSTSTokenInterval: 300000,\r\n bucket,\r\n });\r\n\r\n // 根据并行数选择上传方法\r\n const uploadMethod = uploadOptions.parallel === 1 ? 'put' : 'multipartUpload';\r\n\r\n // 添加进度回调\r\n const progressCallback = onProgress\r\n ? (p: { percent: number; loaded: number; total: number }) => {\r\n onProgress(p);\r\n aliossProgress.trigger({ file, progress: p });\r\n }\r\n : undefined;\r\n\r\n // 处理上传\r\n if (uploadMethod === 'multipartUpload') {\r\n // 分片上传\r\n try {\r\n // 创建一个可取消的上传任务\r\n // 注意:使用as any来绕过TypeScript类型检查,因为ali-oss类型定义可能不完整\r\n const uploadOptions2 = { ...uploadOptions };\r\n if (progressCallback) {\r\n (uploadOptions2 as any).progress = progressCallback;\r\n }\r\n\r\n const uploadPromise = client.multipartUpload(path, file, uploadOptions2 as any);\r\n\r\n // 创建一个取消函数\r\n const cancelFn = () => {\r\n // 注意:ali-oss SDK可能没有直接提供取消方法\r\n // 这里我们需要根据SDK文档调整实际取消逻辑\r\n console.warn('尝试取消上传,但ali-oss SDK可能不支持取消操作');\r\n };\r\n\r\n uploadTasks.set(uid, { cancel: cancelFn });\r\n\r\n // 监听取消信号\r\n if (abortSignal) {\r\n abortSignal.addEventListener('abort', () => {\r\n cancelFn();\r\n });\r\n }\r\n\r\n // 等待上传完成\r\n const result = await uploadPromise;\r\n uploadTasks.delete(uid);\r\n\r\n if (!result || !result.res || result.res.status !== 200) {\r\n throw new AliOssError(`上传失败: ${result?.res ? `HTTP状态码 ${result.res.status}` : '未知错误'}`, 'UPLOAD_FAILED', result);\r\n }\r\n } catch (err) {\r\n uploadTasks.delete(uid);\r\n throw err;\r\n }\r\n } else {\r\n // 普通上传\r\n const result = await client.put(path, file, uploadOptions as any);\r\n\r\n if (!result || !result.res || result.res.status !== 200) {\r\n throw new AliOssError(`上传失败: ${result?.res ? `HTTP状态码 ${result.res.status}` : '未知错误'}`, 'UPLOAD_FAILED', result);\r\n }\r\n }\r\n\r\n // 构建结果URL\r\n const resultUrl = cdn + path;\r\n\r\n // 构建响应对象\r\n const result: AliOssResponse = {\r\n url: resultUrl,\r\n name: finalFileName,\r\n md5: md5Code,\r\n type: fileType,\r\n uid,\r\n lastModified,\r\n size,\r\n isExist: false,\r\n };\r\n\r\n // 如果需要保存到素材库\r\n if (saveStore) {\r\n saveFileToStore(result).catch(error => {\r\n console.error('保存文件到素材库失败:', error);\r\n });\r\n }\r\n\r\n // 触发成功事件\r\n aliossResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n // 移除上传任务\r\n uploadTasks.delete(uid);\r\n\r\n // 处理错误\r\n const err =\r\n error instanceof AliOssError\r\n ? error\r\n : new AliOssError(`上传文件失败: ${error instanceof Error ? error.message : String(error)}`, 'UPLOAD_ERROR', error);\r\n\r\n // 触发错误事件\r\n aliossError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 保存文件到素材库\r\n * @param params 文件保存参数\r\n * @returns 保存结果\r\n */\r\n const saveFileToStore = async (params: AliOssResponse): Promise<AliOssResponse> => {\r\n try {\r\n const { url, md5: md5_code, size: file_size } = params;\r\n const { data } = await postSaveFileResources({ fileData: { url, md5_code, file_size } });\r\n\r\n if (data?.code !== 0) {\r\n const errorMsg = data?.comment || data?.data?.message || '未知错误';\r\n const error = new Error(`保存文件到素材库失败: ${errorMsg}`);\r\n saveFileError.trigger(error);\r\n throw error;\r\n }\r\n\r\n const result = { ...params, existId: data.data.id ?? data.comment };\r\n saveFileResult.trigger(result);\r\n return result;\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(`保存文件到素材库失败: ${String(error)}`);\r\n\r\n saveFileError.trigger(err);\r\n throw err;\r\n }\r\n };\r\n\r\n /**\r\n * 取消文件上传\r\n * @param uid 文件唯一标识\r\n * @returns 是否成功取消\r\n */\r\n const cancelUpload = (uid: number): boolean => {\r\n const task = uploadTasks.get(uid);\r\n if (task) {\r\n task.cancel();\r\n uploadTasks.delete(uid);\r\n return true;\r\n }\r\n return false;\r\n };\r\n\r\n /**\r\n * 取消所有上传任务\r\n */\r\n const cancelAllUploads = (): void => {\r\n uploadTasks.forEach(task => task.cancel());\r\n uploadTasks.clear();\r\n };\r\n\r\n return {\r\n // 事件监听器\r\n aliossResult: aliossResult.on,\r\n aliossError: aliossError.on,\r\n aliossProgress: aliossProgress.on,\r\n saveFileResult: saveFileResult.on,\r\n saveFileError: saveFileError.on,\r\n\r\n // 主要方法\r\n uploadFile,\r\n saveFileToStore,\r\n cancelUpload,\r\n cancelAllUploads,\r\n\r\n // 辅助方法\r\n checkFileExists,\r\n };\r\n});\r\n"],"names":["result"],"mappings":"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"}
@@ -63,3 +63,10 @@ export declare function base64ToBlob(base64: string, options?: FileConversionOpt
63
63
  * @returns
64
64
  */
65
65
  export declare function fileToUrl(file: File | Blob): string;
66
+ export declare function fileValidType(file: File, validTypes: string): boolean;
67
+ /**
68
+ * 计算文件的MD5哈希值
69
+ * @param file 要计算哈希值的文件
70
+ * @returns 文件的MD5哈希值
71
+ */
72
+ export declare const fileMd5: (file: File) => Promise<string>;
@@ -1,3 +1,5 @@
1
+ import { md5 } from 'js-md5';
2
+
1
3
  async function urlToBlob(url) {
2
4
  const response = await fetch(url);
3
5
  return response.blob();
@@ -49,6 +51,42 @@ function base64ToBlob(base64, options) {
49
51
  function fileToUrl(file) {
50
52
  return URL.createObjectURL(file);
51
53
  }
54
+ function fileValidType(file, validTypes) {
55
+ const fileType = file.type || "";
56
+ const fileExtension = file.name.slice(Math.max(0, file.name.lastIndexOf(".")));
57
+ const acceptTypes = validTypes.split(",").map((type) => type.trim());
58
+ return acceptTypes.some((type) => {
59
+ if (type.startsWith(".")) {
60
+ return fileExtension.toLowerCase() === type.toLowerCase();
61
+ } else if (type.includes("/*")) {
62
+ const [mainType] = type.split("/");
63
+ return fileType.startsWith(`${mainType}/`);
64
+ } else {
65
+ return fileType === type;
66
+ }
67
+ });
68
+ }
69
+ const fileMd5 = (file) => {
70
+ return new Promise((resolve, reject) => {
71
+ const reader = new FileReader();
72
+ reader.onload = (e) => {
73
+ try {
74
+ const binary = e.target.result;
75
+ if (binary) {
76
+ resolve(md5(binary));
77
+ } else {
78
+ reject(new Error("\u8BFB\u53D6\u6587\u4EF6\u5185\u5BB9\u5931\u8D25"));
79
+ }
80
+ } catch (error) {
81
+ reject(new Error(`\u8BA1\u7B97MD5\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`));
82
+ }
83
+ };
84
+ reader.onerror = () => {
85
+ reject(new Error("\u8BFB\u53D6\u6587\u4EF6\u5931\u8D25"));
86
+ };
87
+ reader.readAsArrayBuffer(file);
88
+ });
89
+ };
52
90
 
53
- export { base64ToBlob, base64ToFile, blobToBase64, blobToFile, fileToBase64, fileToBlob, fileToUrl, urlToBlob, urlToFile };
91
+ export { base64ToBlob, base64ToFile, blobToBase64, blobToFile, fileMd5, fileToBase64, fileToBlob, fileToUrl, fileValidType, urlToBlob, urlToFile };
54
92
  //# sourceMappingURL=file.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"file.mjs","sources":["../../../../../packages/utils/src/file.ts"],"sourcesContent":["export interface FileConversionOptions {\r\n mimeType?: string;\r\n}\r\n/**\r\n * 将 URL 转换为 Blob\r\n * @param url\r\n * @returns\r\n */\r\nexport async function urlToBlob(url: string): Promise<Blob> {\r\n const response = await fetch(url);\r\n return response.blob();\r\n}\r\n\r\n/**\r\n * 将 URL 转换为 File\r\n * @param url\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport async function urlToFile(url: string, filename: string, options?: FileConversionOptions): Promise<File> {\r\n const blob = await urlToBlob(url);\r\n return new File([blob], filename, { type: options?.mimeType ?? blob.type });\r\n}\r\n\r\n/**\r\n * 将 Base64 字符串转换为 File\r\n * @param base64\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport function base64ToFile(base64: string, filename: string, options?: FileConversionOptions): File {\r\n const bolb = base64ToBlob(base64, { mimeType: options?.mimeType });\r\n return blobToFile(bolb, filename);\r\n}\r\n\r\n/**\r\n * 将 File 转换为 Base64 字符串\r\n * @param file\r\n * @returns\r\n */\r\nexport function fileToBase64(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result as string);\r\n reader.onerror = reject;\r\n reader.readAsDataURL(file);\r\n });\r\n}\r\n\r\n/**\r\n * 将 Blob 转换为 Base64 字符串\r\n * @param blob\r\n * @returns\r\n */\r\nexport function blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result as string);\r\n reader.onerror = reject;\r\n reader.readAsDataURL(blob);\r\n });\r\n}\r\n\r\n/**\r\n * 将 File 转换为 Blob\r\n * @param file\r\n * @param options\r\n * @returns\r\n */\r\nexport function fileToBlob(file: File, options?: FileConversionOptions): Blob {\r\n return new Blob([file], { type: options?.mimeType ?? file.type });\r\n}\r\n\r\n/**\r\n * 将 Blob 转换为 File\r\n * @param blob\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport function blobToFile(blob: Blob, filename: string, options?: FileConversionOptions): File {\r\n return new File([blob], filename, { type: options?.mimeType ?? blob.type });\r\n}\r\n\r\n/**\r\n * 将 Base64 字符串转换为 Blob\r\n * @param base64\r\n * @param options\r\n * @returns\r\n */\r\nexport function base64ToBlob(base64: string, options?: FileConversionOptions): Blob {\r\n const matches = base64.match(/^data:(.+);base64,(.*)$/);\r\n\r\n if (!matches || matches.length !== 3) {\r\n throw new Error('Invalid Base64 string');\r\n }\r\n\r\n const mimeType = options?.mimeType ?? matches[1];\r\n const byteString = atob(matches[2]);\r\n const arrayBuffer = new ArrayBuffer(byteString.length);\r\n const intArray = new Uint8Array(arrayBuffer);\r\n\r\n for (let i = 0; i < byteString.length; i++) {\r\n intArray[i] = byteString.charCodeAt(i);\r\n }\r\n\r\n return new Blob([intArray], { type: mimeType });\r\n}\r\n/**\r\n * 文件转本地url\r\n * @param file\r\n * @returns\r\n */\r\nexport function fileToUrl(file: File | Blob) {\r\n return URL.createObjectURL(file);\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file.mjs","sources":["../../../../../packages/utils/src/file.ts"],"sourcesContent":["import { md5 } from 'js-md5';\r\n\r\nexport interface FileConversionOptions {\r\n mimeType?: string;\r\n}\r\n/**\r\n * 将 URL 转换为 Blob\r\n * @param url\r\n * @returns\r\n */\r\nexport async function urlToBlob(url: string): Promise<Blob> {\r\n const response = await fetch(url);\r\n return response.blob();\r\n}\r\n\r\n/**\r\n * 将 URL 转换为 File\r\n * @param url\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport async function urlToFile(url: string, filename: string, options?: FileConversionOptions): Promise<File> {\r\n const blob = await urlToBlob(url);\r\n return new File([blob], filename, { type: options?.mimeType ?? blob.type });\r\n}\r\n\r\n/**\r\n * 将 Base64 字符串转换为 File\r\n * @param base64\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport function base64ToFile(base64: string, filename: string, options?: FileConversionOptions): File {\r\n const bolb = base64ToBlob(base64, { mimeType: options?.mimeType });\r\n return blobToFile(bolb, filename);\r\n}\r\n\r\n/**\r\n * 将 File 转换为 Base64 字符串\r\n * @param file\r\n * @returns\r\n */\r\nexport function fileToBase64(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result as string);\r\n reader.onerror = reject;\r\n reader.readAsDataURL(file);\r\n });\r\n}\r\n\r\n/**\r\n * 将 Blob 转换为 Base64 字符串\r\n * @param blob\r\n * @returns\r\n */\r\nexport function blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result as string);\r\n reader.onerror = reject;\r\n reader.readAsDataURL(blob);\r\n });\r\n}\r\n\r\n/**\r\n * 将 File 转换为 Blob\r\n * @param file\r\n * @param options\r\n * @returns\r\n */\r\nexport function fileToBlob(file: File, options?: FileConversionOptions): Blob {\r\n return new Blob([file], { type: options?.mimeType ?? file.type });\r\n}\r\n\r\n/**\r\n * 将 Blob 转换为 File\r\n * @param blob\r\n * @param filename\r\n * @param options\r\n * @returns\r\n */\r\nexport function blobToFile(blob: Blob, filename: string, options?: FileConversionOptions): File {\r\n return new File([blob], filename, { type: options?.mimeType ?? blob.type });\r\n}\r\n\r\n/**\r\n * 将 Base64 字符串转换为 Blob\r\n * @param base64\r\n * @param options\r\n * @returns\r\n */\r\nexport function base64ToBlob(base64: string, options?: FileConversionOptions): Blob {\r\n const matches = base64.match(/^data:(.+);base64,(.*)$/);\r\n\r\n if (!matches || matches.length !== 3) {\r\n throw new Error('Invalid Base64 string');\r\n }\r\n\r\n const mimeType = options?.mimeType ?? matches[1];\r\n const byteString = atob(matches[2]);\r\n const arrayBuffer = new ArrayBuffer(byteString.length);\r\n const intArray = new Uint8Array(arrayBuffer);\r\n\r\n for (let i = 0; i < byteString.length; i++) {\r\n intArray[i] = byteString.charCodeAt(i);\r\n }\r\n\r\n return new Blob([intArray], { type: mimeType });\r\n}\r\n/**\r\n * 文件转本地url\r\n * @param file\r\n * @returns\r\n */\r\nexport function fileToUrl(file: File | Blob) {\r\n return URL.createObjectURL(file);\r\n}\r\n\r\n// 导出一个函数,用于检查文件类型是否合法\r\nexport function fileValidType(file: File, validTypes: string) {\r\n // 获取文件的 MIME 类型\r\n const fileType = file.type || '';\r\n // 获取文件的扩展名\r\n const fileExtension = file.name.slice(Math.max(0, file.name.lastIndexOf('.')));\r\n // 将合法的文件类型字符串分割成数组\r\n const acceptTypes = validTypes.split(',').map(type => type.trim());\r\n // 遍历合法的文件类型数组,检查文件类型是否合法\r\n return acceptTypes.some(type => {\r\n // 如果文件类型以 . 开头,则检查文件扩展名\r\n if (type.startsWith('.')) {\r\n // 检查文件扩展名是否与合法的文件类型匹配\r\n return fileExtension.toLowerCase() === type.toLowerCase();\r\n // 如果文件类型包含 /*,则检查 MIME 类型组,如 image/*\r\n } else if (type.includes('/*')) {\r\n // 检查 MIME 类型组,如 image/*\r\n const [mainType] = type.split('/');\r\n return fileType.startsWith(`${mainType}/`);\r\n } else {\r\n // 检查具体 MIME 类型\r\n return fileType === type;\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 计算文件的MD5哈希值\r\n * @param file 要计算哈希值的文件\r\n * @returns 文件的MD5哈希值\r\n */\r\nexport const fileMd5 = (file: File): Promise<string> => {\r\n return new Promise<string>((resolve, reject) => {\r\n const reader = new FileReader();\r\n\r\n reader.onload = e => {\r\n try {\r\n const binary = (e.target as FileReader).result;\r\n if (binary) {\r\n resolve(md5(binary));\r\n } else {\r\n reject(new Error('读取文件内容失败'));\r\n }\r\n } catch (error) {\r\n reject(new Error(`计算MD5失败: ${error instanceof Error ? error.message : String(error)}`));\r\n }\r\n };\r\n\r\n reader.onerror = () => {\r\n reject(new Error('读取文件失败'));\r\n };\r\n\r\n reader.readAsArrayBuffer(file);\r\n });\r\n};\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 粘贴文件处理相关错误类型
3
+ */
4
+ export declare class PasteFileError extends Error {
5
+ originalError?: unknown;
6
+ constructor(message: string, originalError?: unknown);
7
+ }
8
+ /**
9
+ * 生成唯一的文件名
10
+ * @param name 原始文件名(可选)
11
+ * @param ext 文件扩展名(可选)
12
+ * @param prefix 文件名前缀(可选),默认为 'clipboard'
13
+ * @returns 生成的文件名
14
+ */
15
+ export declare const generateFileName: (name?: string, ext?: string, prefix?: string) => string;
16
+ /**
17
+ * 处理粘贴事件,返回粘贴的文件数组
18
+ * @param e 剪贴板事件对象
19
+ * @returns Promise<File[]> 文件对象数组
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // 在事件处理函数中使用
24
+ * document.addEventListener('paste', async (e) => {
25
+ * const files = await handlePasteEvent(e);
26
+ * if (files.length > 0) {
27
+ * console.log('粘贴的文件:', files);
28
+ * // 处理文件...
29
+ * }
30
+ * });
31
+ * ```
32
+ */
33
+ export declare const handlePasteEvent: (e: ClipboardEvent) => Promise<File[]>;