sa2kit 1.6.57 → 1.6.58

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 (145) hide show
  1. package/dist/AliyunOSSProvider-KSYW2IOG.js +15 -0
  2. package/dist/{AliyunOSSProvider-2FARPAQD.js.map → AliyunOSSProvider-KSYW2IOG.js.map} +1 -1
  3. package/dist/AliyunOSSProvider-TBK3G7YK.mjs +6 -0
  4. package/dist/{AliyunOSSProvider-UMVGVBDJ.mjs.map → AliyunOSSProvider-TBK3G7YK.mjs.map} +1 -1
  5. package/dist/LocalStorageProvider-2DGYRQAB.mjs +6 -0
  6. package/dist/{LocalStorageProvider-PYOHETJV.mjs.map → LocalStorageProvider-2DGYRQAB.mjs.map} +1 -1
  7. package/dist/LocalStorageProvider-SSRW3ZJW.js +15 -0
  8. package/dist/{LocalStorageProvider-JQF5WK5H.js.map → LocalStorageProvider-SSRW3ZJW.js.map} +1 -1
  9. package/dist/UniversalFileService-336GFY6N.mjs +6 -0
  10. package/dist/{UniversalFileService-TNYKO6JN.mjs.map → UniversalFileService-336GFY6N.mjs.map} +1 -1
  11. package/dist/UniversalFileService-J6ET6KZK.js +15 -0
  12. package/dist/{UniversalFileService-RBV6EN5J.js.map → UniversalFileService-J6ET6KZK.js.map} +1 -1
  13. package/dist/calendar/index.js +11 -11
  14. package/dist/calendar/index.mjs +4 -4
  15. package/dist/chunk-25OFOKNF.js +171 -0
  16. package/dist/chunk-25OFOKNF.js.map +1 -0
  17. package/dist/chunk-3DXPQ4YV.mjs +165 -0
  18. package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
  19. package/dist/{chunk-4VJQZSPU.mjs → chunk-3NHAT7D4.mjs} +3 -4
  20. package/dist/chunk-3NHAT7D4.mjs.map +1 -0
  21. package/dist/{chunk-3JW4X3AC.mjs → chunk-622Y6LTH.mjs} +3 -3
  22. package/dist/{chunk-3JW4X3AC.mjs.map → chunk-622Y6LTH.mjs.map} +1 -1
  23. package/dist/chunk-CIVO4R6N.mjs +37 -0
  24. package/dist/chunk-CIVO4R6N.mjs.map +1 -0
  25. package/dist/{chunk-6BJ76BYC.mjs → chunk-EGJPS7OL.mjs} +3 -3
  26. package/dist/{chunk-6BJ76BYC.mjs.map → chunk-EGJPS7OL.mjs.map} +1 -1
  27. package/dist/{chunk-U7AQC2Z7.js → chunk-EKIOJEJK.js} +1179 -2002
  28. package/dist/chunk-EKIOJEJK.js.map +1 -0
  29. package/dist/{chunk-53WLQ22S.js → chunk-EOWTOG7Y.js} +6 -6
  30. package/dist/{chunk-53WLQ22S.js.map → chunk-EOWTOG7Y.js.map} +1 -1
  31. package/dist/chunk-HDMIOOZY.mjs +546 -0
  32. package/dist/chunk-HDMIOOZY.mjs.map +1 -0
  33. package/dist/{chunk-MZKATHB7.js → chunk-HHVDOIPV.js} +4 -4
  34. package/dist/{chunk-MZKATHB7.js.map → chunk-HHVDOIPV.js.map} +1 -1
  35. package/dist/chunk-HJ6MH7J7.js +552 -0
  36. package/dist/chunk-HJ6MH7J7.js.map +1 -0
  37. package/dist/chunk-KH6RQ4J5.js +28 -0
  38. package/dist/chunk-KH6RQ4J5.js.map +1 -0
  39. package/dist/{chunk-35CXIK5Y.js → chunk-NCOXT7SK.js} +11 -11
  40. package/dist/{chunk-35CXIK5Y.js.map → chunk-NCOXT7SK.js.map} +1 -1
  41. package/dist/chunk-NZZZUMMX.mjs +784 -0
  42. package/dist/chunk-NZZZUMMX.mjs.map +1 -0
  43. package/dist/{chunk-OBIPI4GU.mjs → chunk-OFYBMMWT.mjs} +4 -4
  44. package/dist/{chunk-OBIPI4GU.mjs.map → chunk-OFYBMMWT.mjs.map} +1 -1
  45. package/dist/{chunk-W2NCOORK.js → chunk-PVLLRDUT.js} +951 -145
  46. package/dist/chunk-PVLLRDUT.js.map +1 -0
  47. package/dist/chunk-Q5EDCKQA.js +336 -0
  48. package/dist/chunk-Q5EDCKQA.js.map +1 -0
  49. package/dist/{chunk-6NMIKAE7.mjs → chunk-SNBILYSH.mjs} +5 -5
  50. package/dist/{chunk-6NMIKAE7.mjs.map → chunk-SNBILYSH.mjs.map} +1 -1
  51. package/dist/{chunk-IPY26RQH.js → chunk-UVHPCLP6.js} +5 -5
  52. package/dist/{chunk-IPY26RQH.js.map → chunk-UVHPCLP6.js.map} +1 -1
  53. package/dist/{chunk-V6BXO6ZS.mjs → chunk-WGD2NBVR.mjs} +835 -38
  54. package/dist/chunk-WGD2NBVR.mjs.map +1 -0
  55. package/dist/{chunk-HYZ5C6FY.mjs → chunk-WS3QZYBI.mjs} +1175 -1996
  56. package/dist/chunk-WS3QZYBI.mjs.map +1 -0
  57. package/dist/{chunk-UR5TU4MW.mjs → chunk-XLR6QUDR.mjs} +3 -3
  58. package/dist/{chunk-UR5TU4MW.mjs.map → chunk-XLR6QUDR.mjs.map} +1 -1
  59. package/dist/chunk-YMS6BPXS.js +807 -0
  60. package/dist/chunk-YMS6BPXS.js.map +1 -0
  61. package/dist/chunk-YOTQG4NP.mjs +314 -0
  62. package/dist/chunk-YOTQG4NP.mjs.map +1 -0
  63. package/dist/chunk-ZGVB35L2.mjs +25 -0
  64. package/dist/chunk-ZGVB35L2.mjs.map +1 -0
  65. package/dist/chunk-ZRAW3HXA.js +43 -0
  66. package/dist/chunk-ZRAW3HXA.js.map +1 -0
  67. package/dist/{chunk-4XXIBWCO.js → chunk-ZRWED7Q6.js} +66 -66
  68. package/dist/{chunk-4XXIBWCO.js.map → chunk-ZRWED7Q6.js.map} +1 -1
  69. package/dist/{chunk-DVENFCQY.js → chunk-ZWQJSZEY.js} +4 -5
  70. package/dist/chunk-ZWQJSZEY.js.map +1 -0
  71. package/dist/components/index.js +104 -104
  72. package/dist/components/index.mjs +4 -4
  73. package/dist/index.js +146 -148
  74. package/dist/index.js.map +1 -1
  75. package/dist/index.mjs +8 -11
  76. package/dist/index.mjs.map +1 -1
  77. package/dist/logger/index.js +7 -7
  78. package/dist/logger/index.mjs +1 -4
  79. package/dist/mikuFusionGame/index.js +4 -4
  80. package/dist/mikuFusionGame/index.mjs +3 -3
  81. package/dist/portfolio/index.js +10 -10
  82. package/dist/portfolio/index.mjs +5 -5
  83. package/dist/showmasterpiece/db/index.js +42 -42
  84. package/dist/showmasterpiece/db/index.mjs +1 -1
  85. package/dist/showmasterpiece/index.js +143 -144
  86. package/dist/showmasterpiece/index.js.map +1 -1
  87. package/dist/showmasterpiece/index.mjs +7 -9
  88. package/dist/showmasterpiece/index.mjs.map +1 -1
  89. package/dist/showmasterpiece/logic/index.js +19 -19
  90. package/dist/showmasterpiece/logic/index.mjs +2 -2
  91. package/dist/showmasterpiece/server/index.js +42 -42
  92. package/dist/showmasterpiece/server/index.mjs +1 -1
  93. package/dist/showmasterpiece/ui/web/index.js +34 -34
  94. package/dist/showmasterpiece/ui/web/index.mjs +6 -6
  95. package/dist/universalExport/server/index.js +2 -4
  96. package/dist/universalExport/server/index.js.map +1 -1
  97. package/dist/universalExport/server/index.mjs +1 -3
  98. package/dist/universalExport/server/index.mjs.map +1 -1
  99. package/dist/universalFile/index.js +6 -9
  100. package/dist/universalFile/index.js.map +1 -1
  101. package/dist/universalFile/index.mjs +1 -5
  102. package/dist/universalFile/index.mjs.map +1 -1
  103. package/dist/universalFile/server/index.js +31 -64
  104. package/dist/universalFile/server/index.js.map +1 -1
  105. package/dist/universalFile/server/index.mjs +7 -42
  106. package/dist/universalFile/server/index.mjs.map +1 -1
  107. package/dist/utils/index.js +11 -11
  108. package/dist/utils/index.mjs +2 -2
  109. package/package.json +1 -1
  110. package/dist/AliyunOSSProvider-2FARPAQD.js +0 -15
  111. package/dist/AliyunOSSProvider-UMVGVBDJ.mjs +0 -9
  112. package/dist/LocalStorageProvider-JQF5WK5H.js +0 -15
  113. package/dist/LocalStorageProvider-PYOHETJV.mjs +0 -9
  114. package/dist/UniversalFileService-RBV6EN5J.js +0 -15
  115. package/dist/UniversalFileService-TNYKO6JN.mjs +0 -9
  116. package/dist/chunk-4NFOSCM6.js +0 -34
  117. package/dist/chunk-4NFOSCM6.js.map +0 -1
  118. package/dist/chunk-4VJQZSPU.mjs.map +0 -1
  119. package/dist/chunk-6AHYPPUP.js +0 -344
  120. package/dist/chunk-6AHYPPUP.js.map +0 -1
  121. package/dist/chunk-76V7EKBX.mjs +0 -796
  122. package/dist/chunk-76V7EKBX.mjs.map +0 -1
  123. package/dist/chunk-ACLOJXXE.js +0 -195
  124. package/dist/chunk-ACLOJXXE.js.map +0 -1
  125. package/dist/chunk-AEXPAH7Z.mjs +0 -32
  126. package/dist/chunk-AEXPAH7Z.mjs.map +0 -1
  127. package/dist/chunk-CFGX3EKK.js +0 -560
  128. package/dist/chunk-CFGX3EKK.js.map +0 -1
  129. package/dist/chunk-D2HXMGXS.js +0 -46
  130. package/dist/chunk-D2HXMGXS.js.map +0 -1
  131. package/dist/chunk-DVENFCQY.js.map +0 -1
  132. package/dist/chunk-HYZ5C6FY.mjs.map +0 -1
  133. package/dist/chunk-K7WNCB4V.mjs +0 -554
  134. package/dist/chunk-K7WNCB4V.mjs.map +0 -1
  135. package/dist/chunk-L4ZYBFB2.mjs +0 -44
  136. package/dist/chunk-L4ZYBFB2.mjs.map +0 -1
  137. package/dist/chunk-M4HGHTIC.js +0 -820
  138. package/dist/chunk-M4HGHTIC.js.map +0 -1
  139. package/dist/chunk-PXWDQFWV.mjs +0 -192
  140. package/dist/chunk-PXWDQFWV.mjs.map +0 -1
  141. package/dist/chunk-U7AQC2Z7.js.map +0 -1
  142. package/dist/chunk-V6BXO6ZS.mjs.map +0 -1
  143. package/dist/chunk-VTGPHE4Z.mjs +0 -322
  144. package/dist/chunk-VTGPHE4Z.mjs.map +0 -1
  145. package/dist/chunk-W2NCOORK.js.map +0 -1
@@ -1,796 +0,0 @@
1
- import { init_logger, createLogger } from './chunk-PXWDQFWV.mjs';
2
- import { init_types, StorageProviderError, FileUploadError, FileProcessingError } from './chunk-L4ZYBFB2.mjs';
3
- import { __esm } from './chunk-WMJKH4XE.mjs';
4
- import * as path2 from 'path';
5
- import { EventEmitter } from 'events';
6
- import { v4 } from 'uuid';
7
- import { createHash } from 'crypto';
8
-
9
- function getMimeType(filename) {
10
- const ext = path2.extname(filename).toLowerCase();
11
- return MIME_TYPES[ext] || "application/octet-stream";
12
- }
13
- var MIME_TYPES;
14
- var init_mime = __esm({
15
- "src/universalFile/server/utils/mime.ts"() {
16
- MIME_TYPES = {
17
- // 图片
18
- ".jpg": "image/jpeg",
19
- ".jpeg": "image/jpeg",
20
- ".png": "image/png",
21
- ".gif": "image/gif",
22
- ".webp": "image/webp",
23
- ".svg": "image/svg+xml",
24
- ".bmp": "image/bmp",
25
- ".ico": "image/x-icon",
26
- // 视频
27
- ".mp4": "video/mp4",
28
- ".avi": "video/x-msvideo",
29
- ".mov": "video/quicktime",
30
- ".wmv": "video/x-ms-wmv",
31
- ".flv": "video/x-flv",
32
- ".mkv": "video/x-matroska",
33
- ".webm": "video/webm",
34
- // 音频
35
- ".mp3": "audio/mpeg",
36
- ".wav": "audio/wav",
37
- ".ogg": "audio/ogg",
38
- ".m4a": "audio/mp4",
39
- ".flac": "audio/flac",
40
- ".aac": "audio/aac",
41
- // 文档
42
- ".pdf": "application/pdf",
43
- ".doc": "application/msword",
44
- ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
45
- ".xls": "application/vnd.ms-excel",
46
- ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
47
- ".ppt": "application/vnd.ms-powerpoint",
48
- ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
49
- ".txt": "text/plain",
50
- ".rtf": "application/rtf",
51
- // 压缩文件
52
- ".zip": "application/zip",
53
- ".rar": "application/x-rar-compressed",
54
- ".7z": "application/x-7z-compressed",
55
- ".tar": "application/x-tar",
56
- ".gz": "application/gzip",
57
- // 代码文件
58
- ".js": "application/javascript",
59
- ".json": "application/json",
60
- ".xml": "application/xml",
61
- ".html": "text/html",
62
- ".css": "text/css",
63
- ".ts": "application/typescript",
64
- // 其他
65
- ".csv": "text/csv",
66
- ".md": "text/markdown"
67
- };
68
- }
69
- });
70
- var logger, UniversalFileService;
71
- var init_UniversalFileService = __esm({
72
- "src/universalFile/server/UniversalFileService.ts"() {
73
- init_logger();
74
- init_mime();
75
- init_types();
76
- logger = createLogger("UniversalFileService");
77
- UniversalFileService = class extends EventEmitter {
78
- constructor(config) {
79
- super();
80
- this.storageProviders = /* @__PURE__ */ new Map();
81
- this.cdnProviders = /* @__PURE__ */ new Map();
82
- this.fileProcessors = /* @__PURE__ */ new Map();
83
- this.uploadProgressMap = /* @__PURE__ */ new Map();
84
- this.metadataCache = /* @__PURE__ */ new Map();
85
- this.urlCache = /* @__PURE__ */ new Map();
86
- this.processingQueue = [];
87
- this.isProcessingQueueRunning = false;
88
- this.config = config;
89
- if (this.config.persistence?.enabled && this.config.persistence.repository) {
90
- this.setupPersistenceListeners();
91
- }
92
- }
93
- // ============= 持久化设置 =============
94
- /**
95
- * 设置数据库持久化监听器
96
- *
97
- * 当文件上传完成或删除时,自动触发数据库操作
98
- */
99
- setupPersistenceListeners() {
100
- const { repository, autoPersist = true } = this.config.persistence;
101
- if (!autoPersist) {
102
- logger.info("\u2699\uFE0F [UniversalFileService] \u81EA\u52A8\u6301\u4E45\u5316\u5DF2\u7981\u7528");
103
- return;
104
- }
105
- logger.info("\u2705 [UniversalFileService] \u5DF2\u542F\u7528\u6570\u636E\u5E93\u6301\u4E45\u5316\uFF0C\u81EA\u52A8\u76D1\u542C\u6587\u4EF6\u4E8B\u4EF6");
106
- this.on("upload:complete", async (fileId, data) => {
107
- try {
108
- const metadata = data.metadata || data;
109
- await repository.save(metadata);
110
- logger.info("\u{1F4BE} [Persistence] \u6587\u4EF6\u5143\u6570\u636E\u5DF2\u81EA\u52A8\u4FDD\u5B58: " + fileId);
111
- } catch (error) {
112
- logger.error("\u274C [Persistence] \u4FDD\u5B58\u5931\u8D25: " + fileId, error);
113
- }
114
- });
115
- this.on("file:deleted", async (fileId) => {
116
- try {
117
- await repository.delete(fileId);
118
- logger.info("\u{1F5D1}\uFE0F [Persistence] \u6587\u4EF6\u5143\u6570\u636E\u5DF2\u81EA\u52A8\u5220\u9664: " + fileId);
119
- } catch (error) {
120
- logger.error("\u274C [Persistence] \u5220\u9664\u5931\u8D25: " + fileId, error);
121
- }
122
- });
123
- this.on("files:batch-deleted", async (fileIds) => {
124
- try {
125
- await repository.batchDelete(fileIds);
126
- logger.info("\u{1F5D1}\uFE0F [Persistence] \u6279\u91CF\u5220\u9664\u5143\u6570\u636E: " + fileIds.length + " \u4E2A\u6587\u4EF6");
127
- } catch (error) {
128
- logger.error(`\u274C [Persistence] \u6279\u91CF\u5220\u9664\u5931\u8D25`, error);
129
- }
130
- });
131
- }
132
- // ============= 初始化方法 =============
133
- /**
134
- * 初始化文件服务
135
- */
136
- async initialize() {
137
- logger.info("\u{1F680} [UniversalFileService] \u5F00\u59CB\u521D\u59CB\u5316\u6587\u4EF6\u670D\u52A1...");
138
- try {
139
- await this.validateConfiguration();
140
- await this.initializeStorageProviders();
141
- await this.initializeCDNProviders();
142
- await this.initializeFileProcessors();
143
- logger.info("\u2705 [UniversalFileService] \u6587\u4EF6\u670D\u52A1\u521D\u59CB\u5316\u5B8C\u6210");
144
- } catch (error) {
145
- console.error("\u274C [UniversalFileService] \u6587\u4EF6\u670D\u52A1\u521D\u59CB\u5316\u5931\u8D25:", error);
146
- throw error;
147
- }
148
- }
149
- /**
150
- * 重新初始化存储提供者(支持配置热更新)
151
- */
152
- async reinitializeStorageProviders() {
153
- logger.info("\u{1F504} [UniversalFileService] \u91CD\u65B0\u521D\u59CB\u5316\u5B58\u50A8\u63D0\u4F9B\u8005...");
154
- try {
155
- for (const [type, provider] of this.storageProviders) {
156
- if ("reinitialize" in provider) {
157
- try {
158
- logger.info("\u{1F504} [UniversalFileService] \u91CD\u65B0\u521D\u59CB\u5316\u5B58\u50A8\u63D0\u4F9B\u8005: " + type + "...");
159
- const config = this.config.storageProviders?.[type];
160
- if (config) {
161
- await provider.reinitialize(config);
162
- logger.info("\u2705 [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210: " + type);
163
- } else {
164
- logger.warn("\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u914D\u7F6E\u4E0D\u5B58\u5728: " + type);
165
- }
166
- } catch (error) {
167
- logger.error("\u274C [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25: " + type, error);
168
- }
169
- }
170
- }
171
- logger.info("\u2705 [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u91CD\u65B0\u521D\u59CB\u5316\u5B8C\u6210");
172
- } catch (error) {
173
- console.error("\u274C [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u91CD\u65B0\u521D\u59CB\u5316\u5931\u8D25:", error);
174
- throw error;
175
- }
176
- }
177
- /**
178
- * 注册存储提供者
179
- */
180
- registerStorageProvider(provider) {
181
- this.storageProviders.set(provider.type, provider);
182
- logger.info("\u{1F4E6} [UniversalFileService] \u6CE8\u518C\u5B58\u50A8\u63D0\u4F9B\u8005: " + provider.type);
183
- }
184
- /**
185
- * 注册CDN提供者
186
- */
187
- registerCDNProvider(provider) {
188
- this.cdnProviders.set(provider.type, provider);
189
- logger.info("\u{1F310} [UniversalFileService] \u6CE8\u518CCDN\u63D0\u4F9B\u8005: " + provider.type);
190
- }
191
- /**
192
- * 注册文件处理器
193
- */
194
- registerFileProcessor(processor) {
195
- this.fileProcessors.set(processor.type, processor);
196
- logger.info("\u2699\uFE0F [UniversalFileService] \u6CE8\u518C\u6587\u4EF6\u5904\u7406\u5668: " + processor.type);
197
- }
198
- // ============= 核心文件操作方法 =============
199
- /**
200
- * 上传文件
201
- */
202
- async uploadFile(fileInfo, storageType, onProgress) {
203
- const fileId = v4();
204
- const startTime = Date.now();
205
- logger.info("\u{1F4E4} [UniversalFileService] \u5F00\u59CB\u4E0A\u4F20\u6587\u4EF6: " + fileInfo.file.name + ", ID: " + fileId);
206
- try {
207
- await this.validateFile(fileInfo.file);
208
- const progress = {
209
- fileId,
210
- status: "pending",
211
- progress: 0,
212
- uploadedBytes: 0,
213
- totalBytes: fileInfo.file.size,
214
- speed: 0,
215
- remainingTime: 0
216
- };
217
- this.uploadProgressMap.set(fileId, progress);
218
- this.emitFileEvent("upload:start", fileId, { fileName: fileInfo.file.name });
219
- const metadata = await this.generateFileMetadata(fileId, fileInfo);
220
- const selectedStorageType = storageType || this.config.defaultStorage;
221
- let storageProvider = this.storageProviders.get(selectedStorageType);
222
- if (!storageProvider) {
223
- logger.info(
224
- "\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005 " + selectedStorageType + " \u4E0D\u53EF\u7528\uFF0C\u5C1D\u8BD5\u4F7F\u7528OSS"
225
- );
226
- storageProvider = this.storageProviders.get("aliyun-oss");
227
- if (!storageProvider) {
228
- logger.info(`\u26A0\uFE0F [UniversalFileService] OSS\u4E0D\u53EF\u7528\uFF0C\u56DE\u9000\u5230\u672C\u5730\u5B58\u50A8`);
229
- storageProvider = this.storageProviders.get("local");
230
- }
231
- }
232
- if (!storageProvider) {
233
- throw new StorageProviderError(`\u6CA1\u6709\u53EF\u7528\u7684\u5B58\u50A8\u63D0\u4F9B\u8005`);
234
- }
235
- const storagePath = this.generateStoragePath(metadata);
236
- progress.status = "uploading";
237
- progress.progress = 10;
238
- this.uploadProgressMap.set(fileId, progress);
239
- onProgress?.(progress);
240
- this.emitFileEvent("upload:progress", fileId, { progress: progress.progress });
241
- const uploadResult = await storageProvider.upload(fileInfo, storagePath);
242
- if (!uploadResult.success) {
243
- throw new FileUploadError("\u4E0A\u4F20\u5931\u8D25: " + uploadResult.error);
244
- }
245
- metadata.storagePath = uploadResult.path || storagePath;
246
- metadata.storageProvider = selectedStorageType;
247
- if (this.config.defaultCDN !== "none") {
248
- const cdnProvider = this.cdnProviders.get(this.config.defaultCDN);
249
- if (cdnProvider && uploadResult.url) {
250
- metadata.cdnUrl = await cdnProvider.generateUrl(uploadResult.url);
251
- }
252
- }
253
- progress.status = fileInfo.needsProcessing ? "processing" : "completed";
254
- progress.progress = fileInfo.needsProcessing ? 70 : 100;
255
- this.uploadProgressMap.set(fileId, progress);
256
- onProgress?.(progress);
257
- if (fileInfo.needsProcessing && fileInfo.processingOptions) {
258
- await this.queueFileProcessing(metadata, fileInfo.processingOptions);
259
- }
260
- this.cacheMetadata(metadata);
261
- progress.status = "completed";
262
- progress.progress = 100;
263
- this.uploadProgressMap.set(fileId, progress);
264
- onProgress?.(progress);
265
- const uploadTime = Date.now() - startTime;
266
- logger.info("\u2705 [UniversalFileService] \u6587\u4EF6\u4E0A\u4F20\u5B8C\u6210: " + fileId + ", \u8017\u65F6: " + uploadTime + "ms");
267
- this.emitFileEvent("upload:complete", fileId, {
268
- fileName: fileInfo.file.name,
269
- size: fileInfo.file.size,
270
- uploadTime
271
- });
272
- return metadata;
273
- } catch (error) {
274
- console.error("\u274C [UniversalFileService] \u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: " + fileId + ":", error);
275
- const progress = this.uploadProgressMap.get(fileId);
276
- if (progress) {
277
- progress.status = "failed";
278
- progress.error = error instanceof Error ? error.message : "\u4E0A\u4F20\u5931\u8D25";
279
- this.uploadProgressMap.set(fileId, progress);
280
- onProgress?.(progress);
281
- }
282
- this.emitFileEvent(
283
- "upload:error",
284
- fileId,
285
- void 0,
286
- error instanceof Error ? error.message : "\u4E0A\u4F20\u5931\u8D25"
287
- );
288
- throw error;
289
- } finally {
290
- setTimeout(
291
- () => {
292
- this.uploadProgressMap.delete(fileId);
293
- },
294
- 5 * 60 * 1e3
295
- );
296
- }
297
- }
298
- /**
299
- * 下载文件
300
- */
301
- async downloadFile(fileId, userId) {
302
- logger.info("\u{1F4E5} [UniversalFileService] \u5F00\u59CB\u4E0B\u8F7D\u6587\u4EF6: " + fileId);
303
- try {
304
- this.emitFileEvent("download:start", fileId);
305
- const metadata = await this.getFileMetadata(fileId);
306
- if (!metadata) {
307
- throw new FileUploadError("\u6587\u4EF6\u4E0D\u5B58\u5728: " + fileId);
308
- }
309
- await this.checkFileAccess(metadata, userId);
310
- const storageProvider = this.storageProviders.get(metadata.storageProvider);
311
- if (!storageProvider) {
312
- throw new StorageProviderError("\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: " + metadata.storageProvider);
313
- }
314
- const fileBuffer = await storageProvider.download(metadata.storagePath);
315
- if (this.config.persistence?.enabled) {
316
- await this.updateAccessStats(fileId);
317
- }
318
- logger.info("\u2705 [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5B8C\u6210: " + fileId);
319
- this.emitFileEvent("download:complete", fileId, { size: fileBuffer.length });
320
- return fileBuffer;
321
- } catch (error) {
322
- console.error("\u274C [UniversalFileService] \u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25: " + fileId + ":", error);
323
- this.emitFileEvent("download:error", fileId, void 0, error instanceof Error ? error.message : "\u4E0B\u8F7D\u5931\u8D25");
324
- throw error;
325
- }
326
- }
327
- /**
328
- * 删除文件
329
- */
330
- async deleteFile(fileId, userId) {
331
- logger.info("\u{1F5D1}\uFE0F [UniversalFileService] \u5F00\u59CB\u5220\u9664\u6587\u4EF6: " + fileId);
332
- try {
333
- const metadata = await this.getFileMetadata(fileId);
334
- if (!metadata) {
335
- throw new FileUploadError("\u6587\u4EF6\u4E0D\u5B58\u5728: " + fileId);
336
- }
337
- await this.checkFileDeleteAccess(metadata, userId);
338
- const storageProvider = this.storageProviders.get(metadata.storageProvider);
339
- if (!storageProvider) {
340
- throw new StorageProviderError("\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: " + metadata.storageProvider);
341
- }
342
- const deleteResult = await storageProvider.delete(metadata.storagePath);
343
- if (!deleteResult.success) {
344
- console.warn("\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u6587\u4EF6\u5220\u9664\u5931\u8D25: " + deleteResult.error);
345
- }
346
- if (this.config.persistence?.enabled) {
347
- await this.deleteFileMetadata(fileId);
348
- }
349
- this.clearMetadataCache(fileId);
350
- logger.info("\u2705 [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5B8C\u6210: " + fileId);
351
- this.emitFileEvent("delete:complete", fileId);
352
- this.emit("file:deleted", fileId);
353
- } catch (error) {
354
- console.error("\u274C [UniversalFileService] \u6587\u4EF6\u5220\u9664\u5931\u8D25: " + fileId + ":", error);
355
- this.emitFileEvent("delete:error", fileId, void 0, error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25");
356
- throw error;
357
- }
358
- }
359
- /**
360
- * 获取文件访问URL
361
- */
362
- async getFileUrl(fileId, userId, expiresIn) {
363
- const cacheKey = fileId + "_" + (userId || "public") + "_" + (expiresIn || 0);
364
- const cached = this.urlCache.get(cacheKey);
365
- if (cached && cached.expires > Date.now()) {
366
- return cached.url;
367
- }
368
- const metadata = await this.getFileMetadata(fileId);
369
- if (!metadata) {
370
- throw new FileUploadError("\u6587\u4EF6\u4E0D\u5B58\u5728: " + fileId);
371
- }
372
- await this.checkFileAccess(metadata, userId);
373
- let url;
374
- if (metadata.cdnUrl) {
375
- url = metadata.cdnUrl;
376
- } else {
377
- const storageProvider = this.storageProviders.get(metadata.storageProvider);
378
- if (!storageProvider) {
379
- throw new StorageProviderError("\u5B58\u50A8\u63D0\u4F9B\u8005\u4E0D\u5B58\u5728: " + metadata.storageProvider);
380
- }
381
- url = await storageProvider.getAccessUrl(metadata.storagePath, expiresIn);
382
- }
383
- const cacheExpires = Date.now() + (this.config.cache?.urlTTL || 1800) * 1e3;
384
- this.urlCache.set(cacheKey, { url, expires: cacheExpires });
385
- return url;
386
- }
387
- /**
388
- * 获取文件元数据
389
- */
390
- async getFileMetadata(fileId) {
391
- const cached = this.metadataCache.get(fileId);
392
- if (cached && cached.expires > Date.now()) {
393
- return cached.data;
394
- }
395
- if (this.config.persistence?.enabled && this.config.persistence.repository) {
396
- try {
397
- const metadata = await this.config.persistence.repository.get(fileId);
398
- if (metadata) {
399
- this.cacheMetadata(metadata);
400
- }
401
- return metadata;
402
- } catch (error) {
403
- console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
404
- return null;
405
- }
406
- }
407
- logger.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5143\u6570\u636E: " + fileId);
408
- return null;
409
- }
410
- /**
411
- * 查询文件列表
412
- */
413
- async queryFiles(options) {
414
- if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
415
- logger.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u65E0\u6CD5\u67E5\u8BE2\u6587\u4EF6\u5217\u8868");
416
- return {
417
- items: [],
418
- total: 0,
419
- page: options.page || 1,
420
- pageSize: options.pageSize || 20,
421
- totalPages: 0,
422
- hasNext: false,
423
- hasPrev: false
424
- };
425
- }
426
- try {
427
- const result = await this.config.persistence.repository.query(options);
428
- const hasNext = result.page < result.totalPages;
429
- const hasPrev = result.page > 1;
430
- return {
431
- ...result,
432
- hasNext,
433
- hasPrev
434
- };
435
- } catch (error) {
436
- console.error("\u274C [UniversalFileService] \u67E5\u8BE2\u6587\u4EF6\u5217\u8868\u5931\u8D25:", error);
437
- throw error;
438
- }
439
- }
440
- /**
441
- * 批量删除文件
442
- */
443
- async batchDeleteFiles(fileIds, userId) {
444
- const result = {
445
- successCount: 0,
446
- failureCount: 0,
447
- failures: []
448
- };
449
- for (const fileId of fileIds) {
450
- try {
451
- await this.deleteFile(fileId, userId);
452
- result.successCount++;
453
- } catch (error) {
454
- result.failureCount++;
455
- result.failures.push({
456
- fileId,
457
- error: error instanceof Error ? error.message : "\u5220\u9664\u5931\u8D25"
458
- });
459
- }
460
- }
461
- if (result.successCount > 0) {
462
- this.emit("files:batch-deleted", fileIds.filter((_, i) => i < result.successCount));
463
- }
464
- return result;
465
- }
466
- /**
467
- * 获取上传进度
468
- */
469
- getUploadProgress(fileId) {
470
- return this.uploadProgressMap.get(fileId);
471
- }
472
- // ============= 事件处理方法 =============
473
- /**
474
- * 监听文件事件
475
- */
476
- onFileEvent(eventType, listener) {
477
- this.on(eventType, listener);
478
- }
479
- /**
480
- * 移除文件事件监听器
481
- */
482
- offFileEvent(eventType, listener) {
483
- this.off(eventType, listener);
484
- }
485
- // ============= 私有方法 =============
486
- /**
487
- * 验证配置是否完整
488
- */
489
- async validateConfiguration() {
490
- logger.info("\u{1F50D} [UniversalFileService] \u9A8C\u8BC1\u914D\u7F6E\u6587\u4EF6...");
491
- if (!this.config) {
492
- throw new Error("\u6587\u4EF6\u670D\u52A1\u914D\u7F6E\u4E3A\u7A7A");
493
- }
494
- if (!this.config.storage) {
495
- throw new Error("\u5B58\u50A8\u914D\u7F6E\u4E3A\u7A7A");
496
- }
497
- if (this.config.storage.type === "aliyun-oss") {
498
- const ossConfig = this.config.storage;
499
- if (!ossConfig.accessKeyId || !ossConfig.accessKeySecret || !ossConfig.bucket || !ossConfig.region) {
500
- logger.warn("\u26A0\uFE0F [UniversalFileService] OSS\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u7B49\u5F85\u914D\u7F6E\u52A0\u8F7D...");
501
- const maxRetries = 30;
502
- const retryInterval = 1e3;
503
- for (let i = 0; i < maxRetries; i++) {
504
- await new Promise((resolve) => setTimeout(resolve, retryInterval));
505
- const updatedConfig = this.config.storage;
506
- if (updatedConfig.accessKeyId && updatedConfig.accessKeySecret && updatedConfig.bucket && updatedConfig.region) {
507
- logger.info("\u2705 [UniversalFileService] OSS\u914D\u7F6E\u52A0\u8F7D\u5B8C\u6210");
508
- break;
509
- }
510
- if (i === maxRetries - 1) {
511
- throw new Error("OSS\u914D\u7F6E\u52A0\u8F7D\u8D85\u65F6\uFF1A\u7F3A\u5C11\u5FC5\u9700\u7684\u914D\u7F6E\u9879 (accessKeyId, accessKeySecret, bucket, region)");
512
- }
513
- logger.debug("\u7B49\u5F85OSS\u914D\u7F6E\u52A0\u8F7D\u4E2D... (" + (i + 1) + "/" + maxRetries + ")");
514
- }
515
- }
516
- }
517
- if (!this.config.defaultStorage) {
518
- this.config.defaultStorage = this.config.storage.type;
519
- }
520
- logger.info("\u2705 [UniversalFileService] \u914D\u7F6E\u9A8C\u8BC1\u5B8C\u6210");
521
- }
522
- async initializeStorageProviders() {
523
- logger.info("\u{1F4E6} [UniversalFileService] \u5F00\u59CB\u521D\u59CB\u5316\u5B58\u50A8\u63D0\u4F9B\u8005...");
524
- if (this.storageProviders.size === 0) {
525
- await this.registerDefaultStorageProviders();
526
- }
527
- if (this.config.storageProviders) {
528
- for (const [type, config] of Object.entries(this.config.storageProviders)) {
529
- if (config && config.enabled) {
530
- const provider = this.storageProviders.get(type);
531
- if (provider) {
532
- try {
533
- await provider.initialize(config);
534
- logger.info("\u2705 [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u521D\u59CB\u5316\u5B8C\u6210: " + type);
535
- } catch (error) {
536
- console.warn("\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u521D\u59CB\u5316\u5931\u8D25: " + type + ":", error);
537
- }
538
- } else {
539
- console.warn("\u26A0\uFE0F [UniversalFileService] \u5B58\u50A8\u63D0\u4F9B\u8005\u672A\u6CE8\u518C: " + type);
540
- }
541
- }
542
- }
543
- }
544
- }
545
- async registerDefaultStorageProviders() {
546
- logger.info("\u{1F4E6} [UniversalFileService] \u6CE8\u518C\u9ED8\u8BA4\u5B58\u50A8\u63D0\u4F9B\u8005...");
547
- try {
548
- if (this.config.storage) {
549
- if (this.config.storage.type === "aliyun-oss" && this.config.storage.enabled) {
550
- const { AliyunOSSProvider } = await import('./AliyunOSSProvider-UMVGVBDJ.mjs');
551
- const ossProvider = new AliyunOSSProvider();
552
- this.registerStorageProvider(ossProvider);
553
- logger.info("\u2705 [UniversalFileService] \u963F\u91CC\u4E91OSS\u63D0\u4F9B\u8005\u6CE8\u518C\u6210\u529F");
554
- } else if (this.config.storage.type === "local" && this.config.storage.enabled) {
555
- const { LocalStorageProvider } = await import('./LocalStorageProvider-PYOHETJV.mjs');
556
- const localProvider = new LocalStorageProvider();
557
- this.registerStorageProvider(localProvider);
558
- logger.info("\u2705 [UniversalFileService] \u672C\u5730\u5B58\u50A8\u63D0\u4F9B\u8005\u6CE8\u518C\u6210\u529F");
559
- }
560
- }
561
- if (this.storageProviders.size === 0) {
562
- const { LocalStorageProvider } = await import('./LocalStorageProvider-PYOHETJV.mjs');
563
- const fallbackProvider = new LocalStorageProvider();
564
- this.registerStorageProvider(fallbackProvider);
565
- logger.info("\u2705 [UniversalFileService] \u5DF2\u6CE8\u518C\u5907\u7528\u672C\u5730\u5B58\u50A8\u63D0\u4F9B\u8005");
566
- }
567
- } catch (error) {
568
- console.warn("\u26A0\uFE0F [UniversalFileService] \u6CE8\u518C\u9ED8\u8BA4\u5B58\u50A8\u63D0\u4F9B\u8005\u5931\u8D25:", error);
569
- throw new Error("\u65E0\u6CD5\u521D\u59CB\u5316\u5B58\u50A8\u63D0\u4F9B\u8005");
570
- }
571
- }
572
- async initializeCDNProviders() {
573
- if (this.config.cdn && this.config.cdn.enabled) {
574
- logger.info("\u2705 [UniversalFileService] CDN\u914D\u7F6E\u5DF2\u542F\u7528: " + this.config.cdn.type);
575
- }
576
- }
577
- async initializeFileProcessors() {
578
- for (const processor of Array.from(this.fileProcessors.values())) {
579
- await processor.initialize();
580
- logger.info("\u2705 [UniversalFileService] \u6587\u4EF6\u5904\u7406\u5668\u521D\u59CB\u5316\u5B8C\u6210: " + processor.type);
581
- }
582
- }
583
- async validateFile(file) {
584
- if (this.config.maxFileSize && file.size > this.config.maxFileSize) {
585
- throw new FileUploadError("\u6587\u4EF6\u5927\u5C0F\u8D85\u8FC7\u9650\u5236: " + file.size + " > " + this.config.maxFileSize);
586
- }
587
- const mimeType = file.type || getMimeType(file.name);
588
- if (this.config.allowedMimeTypes && this.config.allowedMimeTypes.length > 0 && !this.config.allowedMimeTypes.includes(mimeType)) {
589
- throw new FileUploadError("\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B: " + mimeType);
590
- }
591
- }
592
- async generateFileMetadata(fileId, fileInfo) {
593
- const now = /* @__PURE__ */ new Date();
594
- const mimeType = fileInfo.file.type || getMimeType(fileInfo.file.name);
595
- const extension = path2.extname(fileInfo.file.name).toLowerCase();
596
- const hash = await this.generateFileHash(fileInfo.file);
597
- return {
598
- id: fileId,
599
- originalName: fileInfo.file.name,
600
- storageName: fileId + extension,
601
- size: fileInfo.file.size,
602
- mimeType,
603
- extension,
604
- hash,
605
- uploadTime: now,
606
- permission: fileInfo.permission || "public",
607
- uploaderId: fileInfo.metadata?.uploadedBy || "system",
608
- moduleId: fileInfo.moduleId,
609
- businessId: fileInfo.businessId,
610
- storageProvider: this.config.defaultStorage || "local",
611
- storagePath: "",
612
- accessCount: 0,
613
- metadata: fileInfo.metadata || {}
614
- };
615
- }
616
- generateStoragePath(metadata) {
617
- const date = /* @__PURE__ */ new Date();
618
- const year = date.getFullYear();
619
- const month = String(date.getMonth() + 1).padStart(2, "0");
620
- const day = String(date.getDate()).padStart(2, "0");
621
- return metadata.moduleId + "/" + year + "/" + month + "/" + day + "/" + metadata.storageName;
622
- }
623
- async generateFileHash(file) {
624
- const buffer = await file.arrayBuffer();
625
- const hash = createHash("sha256");
626
- hash.update(Buffer.from(buffer));
627
- return hash.digest("hex");
628
- }
629
- async queueFileProcessing(metadata, options) {
630
- if (!this.config.processors?.length || 0 > 0) {
631
- return;
632
- }
633
- const processor = this.fileProcessors.get(options.type);
634
- if (!processor) {
635
- console.warn("\u26A0\uFE0F [UniversalFileService] \u6587\u4EF6\u5904\u7406\u5668\u4E0D\u5B58\u5728: " + options.type);
636
- return;
637
- }
638
- if (this.processingQueue.length >= 1e3) {
639
- throw new FileProcessingError("\u5904\u7406\u961F\u5217\u5DF2\u6EE1");
640
- }
641
- this.processingQueue.push({
642
- fileId: metadata.id,
643
- processor,
644
- inputPath: metadata.storagePath,
645
- outputPath: this.generateProcessedPath(metadata, options),
646
- options
647
- });
648
- if (!this.isProcessingQueueRunning) {
649
- this.processFileQueue();
650
- }
651
- }
652
- generateProcessedPath(metadata, options) {
653
- const basePath = metadata.storagePath;
654
- const extension = path2.extname(basePath);
655
- const basename = basePath.replace(extension, "");
656
- return basename + "_processed" + extension;
657
- }
658
- async processFileQueue() {
659
- if (this.isProcessingQueueRunning || this.processingQueue.length === 0) {
660
- return;
661
- }
662
- this.isProcessingQueueRunning = true;
663
- while (this.processingQueue.length > 0) {
664
- const task = this.processingQueue.shift();
665
- if (!task) break;
666
- try {
667
- this.emitFileEvent("processing:start", task.fileId);
668
- const result = await task.processor.process(task.inputPath, task.outputPath, task.options);
669
- if (result.success) {
670
- this.emitFileEvent("processing:complete", task.fileId, result);
671
- } else {
672
- this.emitFileEvent("processing:error", task.fileId, void 0, result.error);
673
- }
674
- } catch (error) {
675
- console.error("\u274C [UniversalFileService] \u6587\u4EF6\u5904\u7406\u5931\u8D25: " + task.fileId + ":", error);
676
- this.emitFileEvent(
677
- "processing:error",
678
- task.fileId,
679
- void 0,
680
- error instanceof Error ? error.message : "\u5904\u7406\u5931\u8D25"
681
- );
682
- }
683
- }
684
- this.isProcessingQueueRunning = false;
685
- }
686
- cacheMetadata(metadata) {
687
- const expires = Date.now() + (this.config.cache?.metadataTTL || 3600) * 1e3;
688
- this.metadataCache.set(metadata.id, { data: metadata, expires });
689
- }
690
- clearMetadataCache(fileId) {
691
- this.metadataCache.delete(fileId);
692
- }
693
- emitFileEvent(type, fileId, data, error) {
694
- const event = {
695
- type,
696
- fileId,
697
- timestamp: /* @__PURE__ */ new Date(),
698
- data,
699
- error
700
- };
701
- this.emit(type, event);
702
- this.emit("*", event);
703
- }
704
- // ============= 数据库操作私有方法 =============
705
- /**
706
- * 保存文件元数据到数据库 (通过持久化仓储)
707
- */
708
- async saveFileMetadata(metadata) {
709
- if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
710
- logger.warn("\u26A0\uFE0F [UniversalFileService] \u6301\u4E45\u5316\u672A\u542F\u7528,\u8DF3\u8FC7\u4FDD\u5B58\u5143\u6570\u636E");
711
- return;
712
- }
713
- try {
714
- await this.config.persistence.repository.save(metadata);
715
- logger.info("\u{1F4BE} [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u4FDD\u5B58\u6210\u529F:", metadata.id);
716
- } catch (error) {
717
- console.error("\u274C [UniversalFileService] \u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
718
- throw new FileUploadError(
719
- "\u4FDD\u5B58\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: " + (error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF")
720
- );
721
- }
722
- }
723
- /**
724
- * 从数据库删除文件元数据 (通过持久化仓储)
725
- */
726
- async deleteFileMetadata(fileId) {
727
- if (!this.config.persistence?.enabled || !this.config.persistence.repository) {
728
- return;
729
- }
730
- try {
731
- await this.config.persistence.repository.delete(fileId);
732
- logger.info("\u{1F5D1}\uFE0F [UniversalFileService] \u6587\u4EF6\u5143\u6570\u636E\u5220\u9664\u6210\u529F:", fileId);
733
- } catch (error) {
734
- console.error("\u274C [UniversalFileService] \u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25:", error);
735
- throw new FileUploadError(
736
- "\u5220\u9664\u6587\u4EF6\u5143\u6570\u636E\u5931\u8D25: " + (error instanceof Error ? error.message : "\u672A\u77E5\u9519\u8BEF")
737
- );
738
- }
739
- }
740
- /**
741
- * 更新访问统计
742
- */
743
- async updateAccessStats(fileId) {
744
- logger.info("\u{1F4CA} [UniversalFileService] \u9700\u8981\u66F4\u65B0\u8BBF\u95EE\u7EDF\u8BA1:", fileId);
745
- }
746
- /**
747
- * 检查文件访问权限
748
- */
749
- async checkFileAccess(metadata, userId) {
750
- if (metadata.permission === "public") {
751
- return;
752
- }
753
- if (metadata.permission === "private" && metadata.uploaderId !== userId) {
754
- throw new FileUploadError("\u65E0\u6743\u9650\u8BBF\u95EE\u6B64\u6587\u4EF6");
755
- }
756
- if (metadata.permission === "authenticated" && !userId) {
757
- throw new FileUploadError("\u9700\u8981\u767B\u5F55\u624D\u80FD\u8BBF\u95EE\u6B64\u6587\u4EF6");
758
- }
759
- }
760
- /**
761
- * 检查文件删除权限
762
- */
763
- async checkFileDeleteAccess(metadata, userId) {
764
- if (metadata.uploaderId !== userId) {
765
- throw new FileUploadError("\u65E0\u6743\u9650\u5220\u9664\u6B64\u6587\u4EF6");
766
- }
767
- }
768
- /**
769
- * 检查服务是否完全可用(包括存储提供者)
770
- */
771
- isFullyInitialized() {
772
- const hasStorageProvider = Array.from(this.storageProviders.values()).some(
773
- (provider) => provider.type === "aliyun-oss" || provider.type === "local"
774
- );
775
- return hasStorageProvider;
776
- }
777
- /**
778
- * 等待服务完全初始化(带超时)
779
- */
780
- async waitForInitialization(timeoutMs = 3e4) {
781
- const startTime = Date.now();
782
- while (!this.isFullyInitialized()) {
783
- if (Date.now() - startTime > timeoutMs) {
784
- throw new Error("\u670D\u52A1\u521D\u59CB\u5316\u8D85\u65F6 (" + timeoutMs + "ms)");
785
- }
786
- await new Promise((resolve) => setTimeout(resolve, 100));
787
- }
788
- logger.info("\u2705 [UniversalFileService] \u670D\u52A1\u5B8C\u5168\u521D\u59CB\u5316\u5C31\u7EEA");
789
- }
790
- };
791
- }
792
- });
793
-
794
- export { UniversalFileService, getMimeType, init_UniversalFileService, init_mime };
795
- //# sourceMappingURL=chunk-76V7EKBX.mjs.map
796
- //# sourceMappingURL=chunk-76V7EKBX.mjs.map