sa2kit 1.0.0
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.
- package/LICENSE +22 -0
- package/README.md +298 -0
- package/dist/AliyunOSSProvider-7JLMJDXK.js +15 -0
- package/dist/AliyunOSSProvider-7JLMJDXK.js.map +1 -0
- package/dist/AliyunOSSProvider-GQMSDJGZ.mjs +6 -0
- package/dist/AliyunOSSProvider-GQMSDJGZ.mjs.map +1 -0
- package/dist/LocalStorageProvider-FVLLHBHO.mjs +6 -0
- package/dist/LocalStorageProvider-FVLLHBHO.mjs.map +1 -0
- package/dist/LocalStorageProvider-NBNHHWLY.js +15 -0
- package/dist/LocalStorageProvider-NBNHHWLY.js.map +1 -0
- package/dist/analytics/index.d.mts +1084 -0
- package/dist/analytics/index.d.ts +1084 -0
- package/dist/analytics/index.js +2595 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +2518 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/analytics/server/index.d.mts +499 -0
- package/dist/analytics/server/index.d.ts +499 -0
- package/dist/analytics/server/index.js +529 -0
- package/dist/analytics/server/index.js.map +1 -0
- package/dist/analytics/server/index.mjs +525 -0
- package/dist/analytics/server/index.mjs.map +1 -0
- package/dist/auth/client/index.d.mts +104 -0
- package/dist/auth/client/index.d.ts +104 -0
- package/dist/auth/client/index.js +21 -0
- package/dist/auth/client/index.js.map +1 -0
- package/dist/auth/client/index.mjs +4 -0
- package/dist/auth/client/index.mjs.map +1 -0
- package/dist/auth/components/index.d.mts +82 -0
- package/dist/auth/components/index.d.ts +82 -0
- package/dist/auth/components/index.js +93 -0
- package/dist/auth/components/index.js.map +1 -0
- package/dist/auth/components/index.mjs +86 -0
- package/dist/auth/components/index.mjs.map +1 -0
- package/dist/auth/hooks/index.d.mts +2 -0
- package/dist/auth/hooks/index.d.ts +2 -0
- package/dist/auth/hooks/index.js +17 -0
- package/dist/auth/hooks/index.js.map +1 -0
- package/dist/auth/hooks/index.mjs +4 -0
- package/dist/auth/hooks/index.mjs.map +1 -0
- package/dist/auth/index.d.mts +15 -0
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.js +110 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +9 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth/middleware/index.d.mts +75 -0
- package/dist/auth/middleware/index.d.ts +75 -0
- package/dist/auth/middleware/index.js +15 -0
- package/dist/auth/middleware/index.js.map +1 -0
- package/dist/auth/middleware/index.mjs +6 -0
- package/dist/auth/middleware/index.mjs.map +1 -0
- package/dist/auth/routes/index.d.mts +163 -0
- package/dist/auth/routes/index.d.ts +163 -0
- package/dist/auth/routes/index.js +27 -0
- package/dist/auth/routes/index.js.map +1 -0
- package/dist/auth/routes/index.mjs +6 -0
- package/dist/auth/routes/index.mjs.map +1 -0
- package/dist/auth/schema/index.d.mts +789 -0
- package/dist/auth/schema/index.d.ts +789 -0
- package/dist/auth/schema/index.js +41 -0
- package/dist/auth/schema/index.js.map +1 -0
- package/dist/auth/schema/index.mjs +4 -0
- package/dist/auth/schema/index.mjs.map +1 -0
- package/dist/auth/services/index.d.mts +47 -0
- package/dist/auth/services/index.d.ts +47 -0
- package/dist/auth/services/index.js +34 -0
- package/dist/auth/services/index.js.map +1 -0
- package/dist/auth/services/index.mjs +5 -0
- package/dist/auth/services/index.mjs.map +1 -0
- package/dist/chunk-3RFBUDRA.js +507 -0
- package/dist/chunk-3RFBUDRA.js.map +1 -0
- package/dist/chunk-3XG5OHFD.mjs +37 -0
- package/dist/chunk-3XG5OHFD.mjs.map +1 -0
- package/dist/chunk-6BL3AZGD.js +285 -0
- package/dist/chunk-6BL3AZGD.js.map +1 -0
- package/dist/chunk-6FNUWAIV.js +394 -0
- package/dist/chunk-6FNUWAIV.js.map +1 -0
- package/dist/chunk-6PRFP5EG.js +171 -0
- package/dist/chunk-6PRFP5EG.js.map +1 -0
- package/dist/chunk-6VHWOPRR.mjs +90 -0
- package/dist/chunk-6VHWOPRR.mjs.map +1 -0
- package/dist/chunk-AIKEVVDR.mjs +122 -0
- package/dist/chunk-AIKEVVDR.mjs.map +1 -0
- package/dist/chunk-APY57REU.js +300 -0
- package/dist/chunk-APY57REU.js.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +10 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/chunk-C64RY2OW.mjs +295 -0
- package/dist/chunk-C64RY2OW.mjs.map +1 -0
- package/dist/chunk-DGUM43GV.js +12 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-FV3FNHQY.js +92 -0
- package/dist/chunk-FV3FNHQY.js.map +1 -0
- package/dist/chunk-GSTLV3MB.mjs +316 -0
- package/dist/chunk-GSTLV3MB.mjs.map +1 -0
- package/dist/chunk-HEMA7SWK.mjs +212 -0
- package/dist/chunk-HEMA7SWK.mjs.map +1 -0
- package/dist/chunk-HWJ34NL6.js +43 -0
- package/dist/chunk-HWJ34NL6.js.map +1 -0
- package/dist/chunk-HXFFYNIF.mjs +385 -0
- package/dist/chunk-HXFFYNIF.mjs.map +1 -0
- package/dist/chunk-KGRQNEIR.mjs +183 -0
- package/dist/chunk-KGRQNEIR.mjs.map +1 -0
- package/dist/chunk-KH6RQ4J5.js +28 -0
- package/dist/chunk-KH6RQ4J5.js.map +1 -0
- package/dist/chunk-KQGP6BTS.mjs +165 -0
- package/dist/chunk-KQGP6BTS.mjs.map +1 -0
- package/dist/chunk-NMF4ANIC.js +365 -0
- package/dist/chunk-NMF4ANIC.js.map +1 -0
- package/dist/chunk-O26VCNS3.js +216 -0
- package/dist/chunk-O26VCNS3.js.map +1 -0
- package/dist/chunk-OLHGZXN3.mjs +86 -0
- package/dist/chunk-OLHGZXN3.mjs.map +1 -0
- package/dist/chunk-QU5OT4DF.js +88 -0
- package/dist/chunk-QU5OT4DF.js.map +1 -0
- package/dist/chunk-RCNNVNLT.mjs +356 -0
- package/dist/chunk-RCNNVNLT.mjs.map +1 -0
- package/dist/chunk-ROEYW4A7.js +186 -0
- package/dist/chunk-ROEYW4A7.js.map +1 -0
- package/dist/chunk-SVWQN2LR.js +131 -0
- package/dist/chunk-SVWQN2LR.js.map +1 -0
- package/dist/chunk-TKCYPDWU.js +338 -0
- package/dist/chunk-TKCYPDWU.js.map +1 -0
- package/dist/chunk-U2L6V7KD.mjs +273 -0
- package/dist/chunk-U2L6V7KD.mjs.map +1 -0
- package/dist/chunk-YVBU7QDJ.mjs +505 -0
- package/dist/chunk-YVBU7QDJ.mjs.map +1 -0
- package/dist/chunk-ZGVB35L2.mjs +25 -0
- package/dist/chunk-ZGVB35L2.mjs.map +1 -0
- package/dist/config/index.d.mts +64 -0
- package/dist/config/index.d.ts +64 -0
- package/dist/config/index.js +136 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +128 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/drizzle-auth-service-Bxlovhv8.d.ts +145 -0
- package/dist/drizzle-auth-service-DZY2F1sv.d.mts +145 -0
- package/dist/enums-Dume-V5Y.d.mts +16 -0
- package/dist/enums-Dume-V5Y.d.ts +16 -0
- package/dist/i18n/index.d.mts +416 -0
- package/dist/i18n/index.d.ts +416 -0
- package/dist/i18n/index.js +671 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/index.mjs +650 -0
- package/dist/i18n/index.mjs.map +1 -0
- package/dist/index-8VoHap_4.d.mts +105 -0
- package/dist/index-8VoHap_4.d.ts +105 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -0
- package/dist/logger/index.d.mts +125 -0
- package/dist/logger/index.d.ts +125 -0
- package/dist/logger/index.js +29 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/index.mjs +4 -0
- package/dist/logger/index.mjs.map +1 -0
- package/dist/request/index.d.mts +51 -0
- package/dist/request/index.d.ts +51 -0
- package/dist/request/index.js +85 -0
- package/dist/request/index.js.map +1 -0
- package/dist/request/index.mjs +82 -0
- package/dist/request/index.mjs.map +1 -0
- package/dist/storage/index.d.mts +74 -0
- package/dist/storage/index.d.ts +74 -0
- package/dist/storage/index.js +46 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/index.mjs +5 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/types-BINlP9MK.d.mts +286 -0
- package/dist/types-BINlP9MK.d.ts +286 -0
- package/dist/types-BaZccpvk.d.mts +48 -0
- package/dist/types-BaZccpvk.d.ts +48 -0
- package/dist/types-CbTsi9CZ.d.mts +31 -0
- package/dist/types-CbTsi9CZ.d.ts +31 -0
- package/dist/types-CoGG1rNV.d.mts +258 -0
- package/dist/types-CoGG1rNV.d.ts +258 -0
- package/dist/types-DAxQ1MeY.d.ts +70 -0
- package/dist/types-DT8LVCvE.d.mts +70 -0
- package/dist/types-DW9qar-w.d.mts +52 -0
- package/dist/types-DW9qar-w.d.ts +52 -0
- package/dist/universalExport/index.d.mts +235 -0
- package/dist/universalExport/index.d.ts +235 -0
- package/dist/universalExport/index.js +621 -0
- package/dist/universalExport/index.js.map +1 -0
- package/dist/universalExport/index.mjs +580 -0
- package/dist/universalExport/index.mjs.map +1 -0
- package/dist/universalExport/server/index.d.mts +429 -0
- package/dist/universalExport/server/index.d.ts +429 -0
- package/dist/universalExport/server/index.js +263 -0
- package/dist/universalExport/server/index.js.map +1 -0
- package/dist/universalExport/server/index.mjs +242 -0
- package/dist/universalExport/server/index.mjs.map +1 -0
- package/dist/universalFile/index.d.mts +310 -0
- package/dist/universalFile/index.d.ts +310 -0
- package/dist/universalFile/index.js +811 -0
- package/dist/universalFile/index.js.map +1 -0
- package/dist/universalFile/index.mjs +736 -0
- package/dist/universalFile/index.mjs.map +1 -0
- package/dist/universalFile/server/index.d.mts +2428 -0
- package/dist/universalFile/server/index.d.ts +2428 -0
- package/dist/universalFile/server/index.js +4578 -0
- package/dist/universalFile/server/index.js.map +1 -0
- package/dist/universalFile/server/index.mjs +4518 -0
- package/dist/universalFile/server/index.mjs.map +1 -0
- package/dist/useElectronStorage-Dj0rcorG.d.mts +65 -0
- package/dist/useElectronStorage-DwnNfIhl.d.ts +65 -0
- package/dist/utils/index.d.mts +188 -0
- package/dist/utils/index.d.ts +188 -0
- package/dist/utils/index.js +42 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +5 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +220 -0
- package/tailwind.animations.js +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/universalFile/server/factory.ts","../../../src/universalFile/server/presets.ts","../../../src/universalFile/server/validation.ts","../../../src/universalFile/server/providers/AliyunCDNProvider.ts","../../../src/universalFile/server/providers/CdnCacheStrategy.ts","../../../src/universalFile/server/processors/ImageProcessor.ts","../../../src/universalFile/server/processors/AudioProcessor.ts","../../../src/universalFile/server/processors/VideoProcessor.ts","../../../src/universalFile/server/processors/ProcessingQueue.ts","../../../src/universalFile/server/utils/mime.ts","../../../src/universalFile/server/UniversalFileService.ts","../../../src/universalFile/server/cache/CacheManager.ts","../../../src/universalFile/server/monitoring/PerformanceMonitor.ts","../../../src/universalFile/server/cdn/CdnCacheStrategy.ts","../../../src/universalFile/server/types/api.ts","../../../src/universalFile/server/errors/ApiError.ts","../../../src/universalFile/server/persistence/drizzle-repository.ts"],"names":["CacheStrategyType","logger","path","fs","existsSync","path2","path4","EventEmitter","uuidv4","AliyunOSSProvider","LocalStorageProvider","path5","createHash","basename","CdnCacheStrategy","ApiErrorCode"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * UniversalFile Service 工厂函数\n * 提供简化的服务初始化方式\n */\n\nimport type {\n UniversalFileServiceConfig,\n StorageConfig,\n LocalStorageConfig,\n AliyunOSSConfig,\n} from './types';\n\n/**\n * 创建文件服务配置(带智能默认值)\n */\nexport function createFileServiceConfig(\n options: Partial<UniversalFileServiceConfig> & {\n storage: StorageConfig | 'local';\n }\n): UniversalFileServiceConfig {\n // 处理简化的 storage 配置\n let storage: StorageConfig;\n\n if (options.storage === 'local') {\n storage = {\n type: 'local',\n enabled: true,\n rootPath: process.env.UPLOAD_DIR || './uploads',\n baseUrl: process.env.BASE_URL || 'http://localhost:3000',\n } as LocalStorageConfig;\n } else {\n storage = options.storage;\n }\n\n return {\n storage,\n cdn: options.cdn,\n cache: options.cache || {\n enabled: false,\n },\n processors: options.processors || [],\n db: options.db,\n maxFileSize: options.maxFileSize || 10 * 1024 * 1024, // 10MB\n allowedMimeTypes: options.allowedMimeTypes || [\n 'image/*',\n 'video/*',\n 'audio/*',\n 'application/pdf',\n ],\n enableMonitoring: options.enableMonitoring !== false,\n };\n}\n\n/**\n * 创建文件服务实例(简化版)\n *\n * @example\n * ```typescript\n * // 最简配置 - 使用本地存储\n * const service = createUniversalFileService({ storage: 'local' });\n *\n * // 标准配置 - 使用阿里云 OSS\n * const service = createUniversalFileService({\n * storage: {\n * type: 'aliyun-oss',\n * config: {\n * accessKeyId: process.env.OSS_KEY!,\n * accessKeySecret: process.env.OSS_SECRET!,\n * bucket: process.env.OSS_BUCKET!,\n * region: process.env.OSS_REGION!,\n * },\n * },\n * db: drizzleDb,\n * });\n * ```\n */\nexport function createUniversalFileService(\n options: Partial<UniversalFileServiceConfig> & {\n storage: StorageConfig | 'local';\n }\n) {\n const config = createFileServiceConfig(options);\n\n // 注意:实际的 UniversalFileService 将在后续 Phase 迁移\n // 这里先返回一个占位对象,包含基本的类型信息\n console.warn(\n '⚠️ UniversalFileService 的完整实现将在后续 Phase 中迁移到 Sa2kit。\\n' +\n ' 当前版本仅包含类型定义和配置工厂函数。\\n' +\n ' 请暂时继续从 LyricNote 的 lib/universalFile 导入服务类。'\n );\n\n return {\n config,\n // 占位方法\n async upload() {\n throw new Error('UniversalFileService 尚未完全迁移,请从 LyricNote 导入');\n },\n async download() {\n throw new Error('UniversalFileService 尚未完全迁移,请从 LyricNote 导入');\n },\n };\n}\n\n/**\n * 从环境变量创建配置(便利函数)\n *\n * @example\n * ```typescript\n * // .env\n * // STORAGE_TYPE=aliyun-oss\n * // OSS_ACCESS_KEY_ID=xxx\n * // OSS_ACCESS_KEY_SECRET=xxx\n * // OSS_BUCKET=my-bucket\n * // OSS_REGION=oss-cn-hangzhou\n *\n * const service = createFileServiceFromEnv();\n * ```\n */\nexport function createFileServiceFromEnv(db?: any) {\n const storageType = process.env.STORAGE_TYPE || 'local';\n\n let storage: StorageConfig;\n\n switch (storageType) {\n case 'local':\n storage = {\n type: 'local',\n enabled: true,\n rootPath: process.env.UPLOAD_DIR || './uploads',\n baseUrl: process.env.BASE_URL || 'http://localhost:3000',\n } as LocalStorageConfig;\n break;\n\n case 'aliyun-oss':\n if (!process.env.OSS_ACCESS_KEY_ID || !process.env.OSS_ACCESS_KEY_SECRET) {\n throw new Error('Missing required OSS environment variables');\n }\n storage = {\n type: 'aliyun-oss',\n enabled: true,\n accessKeyId: process.env.OSS_ACCESS_KEY_ID,\n accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,\n bucket: process.env.OSS_BUCKET!,\n region: process.env.OSS_REGION || 'oss-cn-hangzhou',\n } as AliyunOSSConfig;\n break;\n\n default:\n throw new Error(`Unsupported storage type: ${storageType}`);\n }\n\n return createUniversalFileService({\n storage,\n db,\n });\n}\n\n","/**\n * UniversalFile 预设配置\n * 提供常见场景的开箱即用配置\n */\n\nimport type { StorageConfig, LocalStorageConfig, AliyunOSSConfig } from './types';\n\n/**\n * 本地开发环境预设\n */\nexport function createLocalDevPreset(baseUrl = 'http://localhost:3000'): StorageConfig {\n return {\n type: 'local',\n enabled: true,\n rootPath: './uploads',\n baseUrl,\n } as LocalStorageConfig;\n}\n\n/**\n * 生产环境 OSS 预设\n */\nexport function createAliyunOSSPreset(config: {\n accessKeyId: string;\n accessKeySecret: string;\n bucket: string;\n region?: string;\n}): StorageConfig {\n return {\n type: 'aliyun-oss',\n enabled: true,\n accessKeyId: config.accessKeyId,\n accessKeySecret: config.accessKeySecret,\n bucket: config.bucket,\n region: config.region || 'oss-cn-hangzhou',\n } as AliyunOSSConfig;\n}\n\n/**\n * 智能预设:根据环境自动选择\n */\nexport function createSmartPreset(): StorageConfig {\n const isProduction = process.env.NODE_ENV === 'production';\n\n if (isProduction && process.env.OSS_ACCESS_KEY_ID) {\n // 生产环境且配置了 OSS\n return createAliyunOSSPreset({\n accessKeyId: process.env.OSS_ACCESS_KEY_ID,\n accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,\n bucket: process.env.OSS_BUCKET!,\n region: process.env.OSS_REGION,\n });\n }\n\n // 默认使用本地存储\n return createLocalDevPreset(process.env.BASE_URL);\n}\n\n/**\n * 图片服务预设(针对图片处理优化)\n */\nexport function createImageServicePreset(storage: StorageConfig) {\n return {\n storage,\n maxFileSize: 5 * 1024 * 1024, // 5MB\n allowedMimeTypes: [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/gif',\n ],\n };\n}\n\n/**\n * 视频服务预设(针对大文件优化)\n */\nexport function createVideoServicePreset(storage: StorageConfig) {\n return {\n storage,\n maxFileSize: 100 * 1024 * 1024, // 100MB\n allowedMimeTypes: [\n 'video/mp4',\n 'video/webm',\n 'video/quicktime',\n ],\n enableStreaming: true,\n };\n}\n\n/**\n * 文档服务预设\n */\nexport function createDocumentServicePreset(storage: StorageConfig) {\n return {\n storage,\n maxFileSize: 20 * 1024 * 1024, // 20MB\n allowedMimeTypes: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n ],\n };\n}\n\n","/**\n * UniversalFile 配置验证\n */\n\nimport type { UniversalFileServiceConfig, StorageConfig } from './types';\n\nexport class ConfigValidationError extends Error {\n constructor(message: string, public field: string) {\n super(message);\n this.name = 'ConfigValidationError';\n }\n}\n\n/**\n * 验证存储配置\n */\nexport function validateStorageConfig(storage: StorageConfig): void {\n if (!storage.type) {\n throw new ConfigValidationError('Storage type is required', 'storage.type');\n }\n\n switch (storage.type) {\n case 'local': {\n const config = storage as any;\n if (!config.rootPath) {\n throw new ConfigValidationError(\n 'rootPath is required for local storage',\n 'storage.rootPath'\n );\n }\n if (!config.baseUrl) {\n throw new ConfigValidationError(\n 'baseUrl is required for local storage',\n 'storage.baseUrl'\n );\n }\n break;\n }\n\n case 'aliyun-oss': {\n const config = storage as any;\n if (!config.accessKeyId) {\n throw new ConfigValidationError(\n 'accessKeyId is required for Aliyun OSS',\n 'storage.accessKeyId'\n );\n }\n if (!config.accessKeySecret) {\n throw new ConfigValidationError(\n 'accessKeySecret is required for Aliyun OSS',\n 'storage.accessKeySecret'\n );\n }\n if (!config.bucket) {\n throw new ConfigValidationError(\n 'bucket is required for Aliyun OSS',\n 'storage.bucket'\n );\n }\n break;\n }\n\n default:\n throw new ConfigValidationError(\n `Unsupported storage type: ${storage.type}`,\n 'storage.type'\n );\n }\n}\n\n/**\n * 验证完整的服务配置\n */\nexport function validateServiceConfig(config: UniversalFileServiceConfig): void {\n // 验证存储配置\n if (!config.storage) {\n throw new ConfigValidationError('Storage config is required', 'storage');\n }\n validateStorageConfig(config.storage);\n\n // 验证文件大小限制\n if (config.maxFileSize && config.maxFileSize <= 0) {\n throw new ConfigValidationError(\n 'maxFileSize must be greater than 0',\n 'maxFileSize'\n );\n }\n\n // 验证 MIME 类型\n if (config.allowedMimeTypes && config.allowedMimeTypes.length === 0) {\n throw new ConfigValidationError(\n 'allowedMimeTypes must not be empty',\n 'allowedMimeTypes'\n );\n }\n}\n\n/**\n * 验证环境变量\n */\nexport function validateEnvironment(requiredVars: string[]): void {\n const missing: string[] = [];\n\n for (const varName of requiredVars) {\n if (!process.env[varName]) {\n missing.push(varName);\n }\n }\n\n if (missing.length > 0) {\n throw new ConfigValidationError(\n `Missing required environment variables: ${missing.join(', ')}`,\n 'environment'\n );\n }\n}\n\n/**\n * 获取环境变量所需的变量列表(根据存储类型)\n */\nexport function getRequiredEnvVars(storageType: string): string[] {\n switch (storageType) {\n case 'local':\n return ['UPLOAD_DIR', 'BASE_URL'];\n case 'aliyun-oss':\n return [\n 'OSS_ACCESS_KEY_ID',\n 'OSS_ACCESS_KEY_SECRET',\n 'OSS_BUCKET',\n 'OSS_REGION',\n ];\n default:\n return [];\n }\n}\n\n","/**\n * 阿里云CDN提供者实现\n */\n\nimport { createHash } from 'crypto';\nimport { createLogger } from '../../../logger';\n\nimport type { ICDNProvider, CDNConfig, AliyunCDNConfig, CDNResult, CDNType } from '../types';\n\nimport { CDNProviderError } from '../types';\n\nconst logger = createLogger('AliyunCDNProvider');\n\n// 定义阿里云CDN SDK类型 (简化版本)\ninterface AliyunCDNClient {\n refreshObjectCaches(params: any): Promise<any>;\n pushObjectCache(params: any): Promise<any>;\n describeRefreshTasks(params: any): Promise<any>;\n describePushTasks(params: any): Promise<any>;\n describeDomainConfigs(params: any): Promise<any>;\n describeCdnDomainLogs(params: any): Promise<any>;\n describeDomainRealTimeData(params: any): Promise<any>;\n}\n\n/**\n * 阿里云CDN提供者\n */\nexport class AliyunCDNProvider implements ICDNProvider {\n readonly type: CDNType = 'aliyun-cdn';\n\n private config: AliyunCDNConfig | null = null;\n private client: AliyunCDNClient | null = null;\n private isInitialized = false;\n\n /**\n * 初始化CDN提供者\n */\n async initialize(config: CDNConfig): Promise<void> {\n if (config.type !== 'aliyun-cdn') {\n throw new CDNProviderError('配置类型不匹配:期望 aliyun-cdn');\n }\n\n this.config = config as AliyunCDNConfig;\n\n logger.info(`🌐 [AliyunCDNProvider] 初始化阿里云CDN,域名: ${this.config.domain}`);\n\n try {\n // 验证必需的配置项\n this.validateConfig();\n\n // 注意:这里需要安装阿里云CDN SDK\n // npm install @alicloud/cdn20180510\n try {\n const CDN = require('@alicloud/cdn20180510');\n const OpenApi = require('@alicloud/openapi-client');\n\n const cdnConfig = new OpenApi.Config({\n accessKeyId: this.config.accessKeyId,\n accessKeySecret: this.config.accessKeySecret,\n endpoint: 'cdn.aliyuncs.com',\n });\n\n this.client = new CDN.default(cdnConfig);\n } catch (sdkError) {\n logger.warn('⚠️ [AliyunCDNProvider] 阿里云CDN SDK未安装,使用模拟模式');\n // 创建模拟客户端用于开发测试\n this.client = this.createMockClient();\n }\n\n // 测试连接\n await this.testConnection();\n\n this.isInitialized = true;\n logger.info('✅ [AliyunCDNProvider] 阿里云CDN初始化完成');\n } catch (error) {\n logger.error('❌ [AliyunCDNProvider] 阿里云CDN初始化失败:', error);\n throw new CDNProviderError(\n `阿里云CDN初始化失败: ${error instanceof Error ? error.message : '未知错误'}`\n );\n }\n }\n\n /**\n * 生成CDN URL\n */\n async generateUrl(originalUrl: string): Promise<string> {\n this.ensureInitialized();\n\n logger.info(`🔗 [AliyunCDNProvider] 生成CDN URL: ${originalUrl}`);\n\n try {\n // 解析原始URL\n const url = new URL(originalUrl);\n\n // 替换域名为CDN域名\n const cdnUrl = `${url.protocol}//${this.config!.domain}${url.pathname}${url.search}${url.hash}`;\n\n logger.info(`✅ [AliyunCDNProvider] CDN URL生成完成: ${cdnUrl}`);\n\n return cdnUrl;\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] CDN URL生成失败: ${originalUrl}:`, error);\n throw new CDNProviderError(\n `CDN URL生成失败: ${error instanceof Error ? error.message : '未知错误'}`\n );\n }\n }\n\n /**\n * 刷新缓存\n */\n async refreshCache(urls: string[]): Promise<CDNResult> {\n this.ensureInitialized();\n\n logger.info(`🔄 [AliyunCDNProvider] 开始刷新CDN缓存,URL数量: ${urls.length}`);\n\n try {\n // 将URL转换为CDN URL\n const cdnUrls = await Promise.all(urls.map((url) => this.generateUrl(url)));\n\n // 调用阿里云CDN API刷新缓存\n const result = await this.client!.refreshObjectCaches({\n domainName: this.config!.domain,\n objectPath: cdnUrls.join('\\n'),\n objectType: 'File', // File 或 Directory\n });\n\n logger.info(\n `✅ [AliyunCDNProvider] CDN缓存刷新完成,任务ID: ${result.RefreshTaskId || 'unknown'}`\n );\n\n return {\n success: true,\n data: {\n taskId: result.RefreshTaskId,\n requestId: result.RequestId,\n urls: cdnUrls,\n },\n };\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] CDN缓存刷新失败:`, error);\n\n return {\n success: false,\n error: `CDN缓存刷新失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n /**\n * 预热缓存\n */\n async preheatCache(urls: string[]): Promise<CDNResult> {\n this.ensureInitialized();\n\n logger.info(`🔥 [AliyunCDNProvider] 开始预热CDN缓存,URL数量: ${urls.length}`);\n\n try {\n // 将URL转换为CDN URL\n const cdnUrls = await Promise.all(urls.map((url) => this.generateUrl(url)));\n\n // 调用阿里云CDN API预热缓存\n const result = await this.client!.pushObjectCache({\n domainName: this.config!.domain,\n objectPath: cdnUrls.join('\\n'),\n area: 'domestic', // domestic, overseas, global\n });\n\n logger.info(\n `✅ [AliyunCDNProvider] CDN缓存预热完成,任务ID: ${result.PushTaskId || 'unknown'}`\n );\n\n return {\n success: true,\n data: {\n taskId: result.PushTaskId,\n requestId: result.RequestId,\n urls: cdnUrls,\n },\n };\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] CDN缓存预热失败:`, error);\n\n return {\n success: false,\n error: `CDN缓存预热失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n /**\n * 获取访问统计\n */\n async getAccessStats(startTime: Date, endTime: Date): Promise<CDNResult> {\n this.ensureInitialized();\n\n logger.info(\n `📊 [AliyunCDNProvider] 获取CDN访问统计: ${startTime.toISOString()} - ${endTime.toISOString()}`\n );\n\n try {\n // 格式化时间\n const formatTime = (date: Date) => date.toISOString().slice(0, 19).replace('T', ' ') + 'Z';\n\n // 调用阿里云CDN API获取实时数据\n const result = await this.client!.describeDomainRealTimeData({\n domainName: this.config!.domain,\n startTime: formatTime(startTime),\n endTime: formatTime(endTime),\n field: 'bps,qps', // 带宽和QPS\n });\n\n logger.info(`✅ [AliyunCDNProvider] CDN访问统计获取完成`);\n\n return {\n success: true,\n data: {\n requestId: result.RequestId,\n dataInterval: result.DataInterval,\n realTimeData: result.RealTimeData,\n domain: this.config!.domain,\n startTime: startTime.toISOString(),\n endTime: endTime.toISOString(),\n },\n };\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] CDN访问统计获取失败:`, error);\n\n return {\n success: false,\n error: `CDN访问统计获取失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n // ============= 高级功能 =============\n\n /**\n * 生成防盗链签名URL\n */\n async generateSignedUrl(\n originalUrl: string,\n expiresIn: number = 3600,\n authKey?: string\n ): Promise<string> {\n this.ensureInitialized();\n\n logger.info(`🔐 [AliyunCDNProvider] 生成防盗链签名URL: ${originalUrl}`);\n\n try {\n const cdnUrl = await this.generateUrl(originalUrl);\n\n // 如果没有提供authKey,直接返回CDN URL\n if (!authKey) {\n logger.info(`⚠️ [AliyunCDNProvider] 未提供authKey,返回普通CDN URL`);\n return cdnUrl;\n }\n\n // 生成防盗链签名\n const parsedUrl = new URL(cdnUrl);\n const timestamp = Math.floor(Date.now() / 1000) + expiresIn;\n\n // 阿里云CDN防盗链签名算法\n // signString = \"path-timestamp-rand-uid-authKey\"\n const signString = `${parsedUrl.pathname}-${timestamp}-0-0-${authKey}`;\n const authValue = createHash('md5').update(signString).digest('hex');\n\n // 构建签名URL\n const signedUrl = `${cdnUrl}?auth_key=${timestamp}-0-0-${authValue}`;\n\n logger.info(`✅ [AliyunCDNProvider] 防盗链签名URL生成完成`);\n\n return signedUrl;\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] 防盗链签名URL生成失败: ${originalUrl}:`, error);\n throw new CDNProviderError(\n `防盗链签名URL生成失败: ${error instanceof Error ? error.message : '未知错误'}`\n );\n }\n }\n\n /**\n * 查询刷新任务状态\n */\n async getRefreshTaskStatus(taskId: string): Promise<CDNResult> {\n this.ensureInitialized();\n\n try {\n const result = await this.client!.describeRefreshTasks({\n taskId,\n });\n\n return {\n success: true,\n data: {\n tasks: result.Tasks,\n requestId: result.RequestId,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: `查询刷新任务状态失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n /**\n * 查询预热任务状态\n */\n async getPreheatTaskStatus(taskId: string): Promise<CDNResult> {\n this.ensureInitialized();\n\n try {\n const result = await this.client!.describePushTasks({\n taskId,\n });\n\n return {\n success: true,\n data: {\n tasks: result.Tasks,\n requestId: result.RequestId,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: `查询预热任务状态失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n /**\n * 获取域名配置\n */\n async getDomainConfig(): Promise<CDNResult> {\n this.ensureInitialized();\n\n try {\n const result = await this.client!.describeDomainConfigs({\n domainName: this.config!.domain,\n });\n\n return {\n success: true,\n data: {\n domainConfigs: result.DomainConfigs,\n requestId: result.RequestId,\n },\n };\n } catch (error) {\n return {\n success: false,\n error: `获取域名配置失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n\n /**\n * 优化URL (添加图像处理参数等)\n */\n async optimizeUrl(\n originalUrl: string,\n options: {\n imageQuality?: number;\n imageFormat?: 'webp' | 'jpg' | 'png';\n imageResize?: { width?: number; height?: number };\n enableGzip?: boolean;\n } = {}\n ): Promise<string> {\n this.ensureInitialized();\n\n try {\n const cdnUrl = await this.generateUrl(originalUrl);\n const url = new URL(cdnUrl);\n\n // 添加阿里云CDN图像处理参数\n const params = new URLSearchParams(url.search);\n\n if (options.imageQuality) {\n params.set('x-oss-process', `image/quality,q_${options.imageQuality}`);\n }\n\n if (options.imageFormat) {\n const formatParam = params.get('x-oss-process') || 'image';\n params.set('x-oss-process', `${formatParam}/format,${options.imageFormat}`);\n }\n\n if (options.imageResize) {\n const resizeParam = params.get('x-oss-process') || 'image';\n let resize = 'resize';\n if (options.imageResize.width) resize += `,w_${options.imageResize.width}`;\n if (options.imageResize.height) resize += `,h_${options.imageResize.height}`;\n params.set('x-oss-process', `${resizeParam}/${resize}`);\n }\n\n url.search = params.toString();\n\n return url.toString();\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] URL优化失败: ${originalUrl}:`, error);\n // 如果优化失败,返回原始CDN URL\n return this.generateUrl(originalUrl);\n }\n }\n\n // ============= 私有方法 =============\n\n /**\n * 确保已初始化\n */\n private ensureInitialized(): void {\n if (!this.isInitialized || !this.client || !this.config) {\n throw new CDNProviderError('CDN提供者未初始化');\n }\n }\n\n /**\n * 验证配置\n */\n private validateConfig(): void {\n if (!this.config) {\n throw new CDNProviderError('CDN配置为空');\n }\n\n const required = ['domain', 'accessKeyId', 'accessKeySecret'];\n const missing = required.filter((key) => !this.config![key as keyof AliyunCDNConfig]);\n\n if (missing.length > 0) {\n throw new CDNProviderError(`CDN配置缺少必需项: ${missing.join(', ')}`);\n }\n\n // 验证域名格式\n if (!this.isValidDomain(this.config.domain)) {\n throw new CDNProviderError(`无效的CDN域名: ${this.config.domain}`);\n }\n }\n\n /**\n * 验证域名格式\n */\n private isValidDomain(domain: string): boolean {\n // 简单的域名格式验证\n const domainRegex =\n /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n return domainRegex.test(domain);\n }\n\n /**\n * 测试连接\n */\n private async testConnection(): Promise<void> {\n try {\n // 尝试获取域名配置来测试连接\n await this.getDomainConfig();\n logger.info(`✅ [AliyunCDNProvider] CDN连接测试成功`);\n } catch (error) {\n logger.warn(`⚠️ [AliyunCDNProvider] CDN连接测试失败,可能是权限问题:`, error);\n // 不抛出错误,因为可能是权限限制\n }\n }\n\n /**\n * 创建模拟客户端(用于开发测试)\n */\n private createMockClient(): AliyunCDNClient {\n logger.info('🧪 [AliyunCDNProvider] 创建模拟CDN客户端');\n\n return {\n async refreshObjectCaches(params: any) {\n logger.info('🔄 [MockCDN] 模拟刷新缓存:', params);\n return {\n RefreshTaskId: `mock-refresh-${Date.now()}`,\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async pushObjectCache(params: any) {\n logger.info('🔥 [MockCDN] 模拟预热缓存:', params);\n return {\n PushTaskId: `mock-push-${Date.now()}`,\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async describeRefreshTasks(params: any) {\n logger.info('📋 [MockCDN] 模拟查询刷新任务:', params);\n return {\n Tasks: {\n Task: [\n {\n TaskId: params.taskId,\n Status: 'Complete',\n Process: '100%',\n CreateTime: new Date().toISOString(),\n },\n ],\n },\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async describePushTasks(params: any) {\n logger.info('📋 [MockCDN] 模拟查询预热任务:', params);\n return {\n Tasks: {\n Task: [\n {\n TaskId: params.taskId,\n Status: 'Complete',\n Process: '100%',\n CreateTime: new Date().toISOString(),\n },\n ],\n },\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async describeDomainConfigs(params: any) {\n logger.info('⚙️ [MockCDN] 模拟获取域名配置:', params);\n return {\n DomainConfigs: {\n DomainConfig: [\n {\n FunctionName: 'cache',\n ConfigId: 'mock-config-id',\n Status: 'success',\n },\n ],\n },\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async describeCdnDomainLogs(params: any) {\n logger.info('📊 [MockCDN] 模拟获取日志:', params);\n return {\n DomainLogDetails: {\n DomainLogDetail: [],\n },\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n\n async describeDomainRealTimeData(params: any) {\n logger.info('📈 [MockCDN] 模拟获取实时数据:', params);\n return {\n RealTimeData: {\n UsageData: [\n {\n TimeStamp: new Date().toISOString(),\n Value: Math.random() * 1000,\n },\n ],\n },\n DataInterval: '60',\n RequestId: `mock-request-${Date.now()}`,\n };\n },\n };\n }\n\n /**\n * 批量刷新缓存(带进度回调)\n */\n async batchRefreshCache(\n urls: string[],\n batchSize: number = 20,\n onProgress?: (completed: number, total: number) => void\n ): Promise<CDNResult> {\n this.ensureInitialized();\n\n logger.info(\n `🔄 [AliyunCDNProvider] 开始批量刷新缓存,总URL数: ${urls.length},批次大小: ${batchSize}`\n );\n\n try {\n const results = [];\n let completed = 0;\n\n // 分批处理\n for (let i = 0; i < urls.length; i += batchSize) {\n const batch = urls.slice(i, i + batchSize);\n const batchResult = await this.refreshCache(batch);\n results.push(batchResult);\n\n completed += batch.length;\n if (onProgress) {\n onProgress(completed, urls.length);\n }\n\n // 避免API限流,每批次间隔1秒\n if (i + batchSize < urls.length) {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n logger.info(`✅ [AliyunCDNProvider] 批量刷新完成,成功: ${successCount}/${results.length}`);\n\n return {\n success: successCount === results.length,\n data: {\n totalBatches: results.length,\n successBatches: successCount,\n results,\n },\n };\n } catch (error) {\n logger.error(`❌ [AliyunCDNProvider] 批量刷新失败:`, error);\n\n return {\n success: false,\n error: `批量刷新失败: ${error instanceof Error ? error.message : '未知错误'}`,\n };\n }\n }\n}\n\n","/**\n * CDN缓存策略管理\n * 优化静态资源缓存策略和预热机制\n */\n\n/**\n * 缓存策略类型\n */\nexport enum CacheStrategyType {\n /** 图片资源 */\n IMAGE = 'image',\n /** 视频资源 */\n VIDEO = 'video',\n /** 音频资源 */\n AUDIO = 'audio',\n /** 文档资源 */\n DOCUMENT = 'document',\n /** 压缩包 */\n ARCHIVE = 'archive',\n /** 静态资源 */\n STATIC = 'static',\n /** 其他 */\n OTHER = 'other',\n}\n\n/**\n * 缓存策略配置\n */\ninterface CacheStrategyConfig {\n /** 缓存策略类型 */\n type: CacheStrategyType;\n /** 缓存时间(秒) */\n ttl: number;\n /** 是否启用浏览器缓存 */\n browserCache: boolean;\n /** 浏览器缓存时间(秒) */\n browserCacheTtl: number;\n /** 是否启用CDN缓存 */\n cdnCache: boolean;\n /** CDN缓存时间(秒) */\n cdnCacheTtl: number;\n /** 是否启用预热 */\n enableWarmup: boolean;\n /** 缓存控制头 */\n cacheControl: string;\n /** 允许的文件类型 */\n allowedMimeTypes: string[];\n /** 文件大小限制(字节) */\n maxFileSize?: number;\n}\n\n/**\n * 缓存统计信息\n */\ninterface CacheStats {\n /** 命中次数 */\n hits: number;\n /** 未命中次数 */\n misses: number;\n /** 命中率 */\n hitRate: number;\n /** 总请求数 */\n totalRequests: number;\n /** 缓存大小估算 */\n estimatedSize: number;\n /** 节省的带宽(字节) */\n bandwidthSaved: number;\n}\n\n/**\n * CDN缓存策略管理器\n */\nexport class CdnCacheStrategy {\n private strategies: Map<CacheStrategyType, CacheStrategyConfig> = new Map();\n private stats: Map<CacheStrategyType, CacheStats> = new Map();\n\n constructor() {\n this.initializeDefaultStrategies();\n }\n\n /**\n * 初始化默认缓存策略\n */\n private initializeDefaultStrategies(): void {\n // 图片缓存策略\n this.strategies.set(CacheStrategyType.IMAGE, {\n type: CacheStrategyType.IMAGE,\n ttl: 30 * 24 * 3600, // 30天\n browserCache: true,\n browserCacheTtl: 7 * 24 * 3600, // 7天\n cdnCache: true,\n cdnCacheTtl: 30 * 24 * 3600, // 30天\n enableWarmup: true,\n cacheControl: 'public, max-age=604800, s-maxage=2592000',\n allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'],\n maxFileSize: 50 * 1024 * 1024, // 50MB\n });\n\n // 视频缓存策略\n this.strategies.set(CacheStrategyType.VIDEO, {\n type: CacheStrategyType.VIDEO,\n ttl: 7 * 24 * 3600, // 7天\n browserCache: true,\n browserCacheTtl: 24 * 3600, // 1天\n cdnCache: true,\n cdnCacheTtl: 7 * 24 * 3600, // 7天\n enableWarmup: false, // 视频文件通常较大,不预热\n cacheControl: 'public, max-age=86400, s-maxage=604800',\n allowedMimeTypes: ['video/mp4', 'video/avi', 'video/mov', 'video/wmv', 'video/webm'],\n maxFileSize: 500 * 1024 * 1024, // 500MB\n });\n\n // 音频缓存策略\n this.strategies.set(CacheStrategyType.AUDIO, {\n type: CacheStrategyType.AUDIO,\n ttl: 14 * 24 * 3600, // 14天\n browserCache: true,\n browserCacheTtl: 3 * 24 * 3600, // 3天\n cdnCache: true,\n cdnCacheTtl: 14 * 24 * 3600, // 14天\n enableWarmup: true,\n cacheControl: 'public, max-age=259200, s-maxage=1209600',\n allowedMimeTypes: ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/m4a', 'audio/flac'],\n maxFileSize: 100 * 1024 * 1024, // 100MB\n });\n\n // 文档缓存策略\n this.strategies.set(CacheStrategyType.DOCUMENT, {\n type: CacheStrategyType.DOCUMENT,\n ttl: 24 * 3600, // 1天\n browserCache: true,\n browserCacheTtl: 3600, // 1小时\n cdnCache: true,\n cdnCacheTtl: 24 * 3600, // 1天\n enableWarmup: false,\n cacheControl: 'public, max-age=3600, s-maxage=86400',\n allowedMimeTypes: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/plain',\n 'text/csv',\n ],\n maxFileSize: 50 * 1024 * 1024, // 50MB\n });\n\n // 压缩包缓存策略\n this.strategies.set(CacheStrategyType.ARCHIVE, {\n type: CacheStrategyType.ARCHIVE,\n ttl: 24 * 3600, // 1天\n browserCache: true,\n browserCacheTtl: 1800, // 30分钟\n cdnCache: true,\n cdnCacheTtl: 24 * 3600, // 1天\n enableWarmup: false,\n cacheControl: 'public, max-age=1800, s-maxage=86400',\n allowedMimeTypes: [\n 'application/zip',\n 'application/x-rar-compressed',\n 'application/x-7z-compressed',\n 'application/gzip',\n 'application/x-tar',\n ],\n maxFileSize: 100 * 1024 * 1024, // 100MB\n });\n\n // 静态资源缓存策略\n this.strategies.set(CacheStrategyType.STATIC, {\n type: CacheStrategyType.STATIC,\n ttl: 365 * 24 * 3600, // 1年\n browserCache: true,\n browserCacheTtl: 30 * 24 * 3600, // 30天\n cdnCache: true,\n cdnCacheTtl: 365 * 24 * 3600, // 1年\n enableWarmup: true,\n cacheControl: 'public, max-age=2592000, s-maxage=31536000, immutable',\n allowedMimeTypes: [\n 'text/css',\n 'application/javascript',\n 'application/json',\n 'font/woff',\n 'font/woff2',\n 'font/ttf',\n ],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n });\n\n // 其他文件缓存策略\n this.strategies.set(CacheStrategyType.OTHER, {\n type: CacheStrategyType.OTHER,\n ttl: 3600, // 1小时\n browserCache: true,\n browserCacheTtl: 300, // 5分钟\n cdnCache: false,\n cdnCacheTtl: 0,\n enableWarmup: false,\n cacheControl: 'public, max-age=300',\n allowedMimeTypes: [],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n });\n\n // 初始化统计信息\n for (const type of Object.values(CacheStrategyType)) {\n this.stats.set(type, {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n });\n }\n }\n\n /**\n * 根据MIME类型获取缓存策略\n */\n getStrategyByMimeType(mimeType: string): CacheStrategyConfig {\n for (const [_type, strategy] of this.strategies.entries()) {\n if (strategy.allowedMimeTypes.includes(mimeType)) {\n return strategy;\n }\n }\n\n // 根据MIME类型推断策略\n if (mimeType.startsWith('image/')) {\n return this.strategies.get(CacheStrategyType.IMAGE)!;\n } else if (mimeType.startsWith('video/')) {\n return this.strategies.get(CacheStrategyType.VIDEO)!;\n } else if (mimeType.startsWith('audio/')) {\n return this.strategies.get(CacheStrategyType.AUDIO)!;\n } else if (\n mimeType.includes('pdf') ||\n mimeType.includes('document') ||\n mimeType.includes('word') ||\n mimeType.includes('excel')\n ) {\n return this.strategies.get(CacheStrategyType.DOCUMENT)!;\n } else if (\n mimeType.includes('zip') ||\n mimeType.includes('compressed') ||\n mimeType.includes('archive')\n ) {\n return this.strategies.get(CacheStrategyType.ARCHIVE)!;\n }\n\n return this.strategies.get(CacheStrategyType.OTHER)!;\n }\n\n /**\n * 生成缓存控制头\n */\n generateCacheHeaders(mimeType: string, fileSize?: number): Record<string, string> {\n const strategy = this.getStrategyByMimeType(mimeType);\n\n // 检查文件大小限制\n if (fileSize && strategy.maxFileSize && fileSize > strategy.maxFileSize) {\n // 大文件使用更短的缓存时间\n return {\n 'Cache-Control': 'public, max-age=300', // 5分钟\n Expires: new Date(Date.now() + 300 * 1000).toUTCString(),\n };\n }\n\n const headers: Record<string, string> = {\n 'Cache-Control': strategy.cacheControl,\n Expires: new Date(Date.now() + strategy.browserCacheTtl * 1000).toUTCString(),\n };\n\n // 添加ETag用于缓存验证\n if (strategy.browserCache) {\n headers['ETag'] = `\"${Date.now()}\"`;\n }\n\n // 添加Last-Modified头\n headers['Last-Modified'] = new Date().toUTCString();\n\n // 为静态资源添加不可变标记\n if (strategy.type === CacheStrategyType.STATIC) {\n headers['Cache-Control'] += ', immutable';\n }\n\n return headers;\n }\n\n /**\n * 检查是否需要缓存预热\n */\n shouldWarmupCache(mimeType: string): boolean {\n const strategy = this.getStrategyByMimeType(mimeType);\n return strategy.enableWarmup;\n }\n\n /**\n * 记录缓存命中\n */\n recordCacheHit(mimeType: string, fileSize: number = 0): void {\n const strategy = this.getStrategyByMimeType(mimeType);\n const stats = this.stats.get(strategy.type);\n\n if (stats) {\n stats.hits++;\n stats.totalRequests++;\n stats.bandwidthSaved += fileSize;\n stats.hitRate = (stats.hits / stats.totalRequests) * 100;\n }\n }\n\n /**\n * 记录缓存未命中\n */\n recordCacheMiss(mimeType: string, fileSize: number = 0): void {\n const strategy = this.getStrategyByMimeType(mimeType);\n const stats = this.stats.get(strategy.type);\n\n if (stats) {\n stats.misses++;\n stats.totalRequests++;\n stats.estimatedSize += fileSize;\n stats.hitRate = (stats.hits / stats.totalRequests) * 100;\n }\n }\n\n /**\n * 获取缓存统计信息\n */\n getCacheStats(): Map<CacheStrategyType, CacheStats> {\n return new Map(this.stats);\n }\n\n /**\n * 获取总体缓存统计\n */\n getOverallStats(): CacheStats {\n const overall: CacheStats = {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n };\n\n for (const stats of this.stats.values()) {\n overall.hits += stats.hits;\n overall.misses += stats.misses;\n overall.totalRequests += stats.totalRequests;\n overall.estimatedSize += stats.estimatedSize;\n overall.bandwidthSaved += stats.bandwidthSaved;\n }\n\n overall.hitRate = overall.totalRequests > 0 ? (overall.hits / overall.totalRequests) * 100 : 0;\n\n return overall;\n }\n\n /**\n * 生成缓存优化建议\n */\n generateOptimizationSuggestions(): Array<{\n type: CacheStrategyType;\n issue: string;\n suggestion: string;\n severity: 'low' | 'medium' | 'high';\n }> {\n const suggestions: Array<{\n type: CacheStrategyType;\n issue: string;\n suggestion: string;\n severity: 'low' | 'medium' | 'high';\n }> = [];\n\n for (const [type, stats] of this.stats.entries()) {\n if (stats.totalRequests > 100) {\n // 只对有足够请求量的资源类型分析\n // 命中率过低\n if (stats.hitRate < 60) {\n suggestions.push({\n type,\n issue: `${type}类型文件缓存命中率过低 (${stats.hitRate.toFixed(1)}%)`,\n suggestion: '考虑增加缓存时间或启用预热机制',\n severity: stats.hitRate < 30 ? 'high' : 'medium',\n });\n }\n\n // 缓存大小过大\n if (stats.estimatedSize > 1024 * 1024 * 1024) {\n // 1GB\n suggestions.push({\n type,\n issue: `${type}类型文件缓存占用空间过大 (${(stats.estimatedSize / 1024 / 1024 / 1024).toFixed(2)}GB)`,\n suggestion: '考虑减少缓存时间或优化文件压缩',\n severity: 'medium',\n });\n }\n }\n }\n\n return suggestions;\n }\n\n /**\n * 更新缓存策略\n */\n updateStrategy(type: CacheStrategyType, config: Partial<CacheStrategyConfig>): void {\n const currentStrategy = this.strategies.get(type);\n if (currentStrategy) {\n this.strategies.set(type, { ...currentStrategy, ...config });\n }\n }\n\n /**\n * 重置统计信息\n */\n resetStats(): void {\n for (const type of Object.values(CacheStrategyType)) {\n this.stats.set(type, {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n });\n }\n }\n}\n\n/**\n * 单例CDN缓存策略管理器\n */\nexport const cdnCacheStrategy = new CdnCacheStrategy();\n\n","/**\n * 图片处理器实现\n * 支持压缩、裁剪、水印、格式转换等功能\n */\n\nimport * as path from 'path';\nimport { promises as fs } from 'fs';\nimport { existsSync } from 'fs';\nimport { createLogger } from '../../../logger';\n\nimport type {\n IFileProcessor,\n ProcessorType,\n ProcessingOptions,\n ProcessingResult,\n} from '../types';\n\nimport type { ImageProcessingOptions } from '../../types';\n\nconst logger = createLogger('ImageProcessor');\n\n// 图片处理相关类型定义\ninterface ImageMetadata {\n format: string;\n width: number;\n height: number;\n channels: number;\n density: number;\n hasAlpha: boolean;\n orientation?: number;\n}\n\n/**\n * 图片处理器\n * 使用Sharp库进行高性能图片处理\n */\nexport class ImageProcessor implements IFileProcessor {\n readonly type: ProcessorType = 'image';\n\n private sharp: any = null;\n private isInitialized = false;\n\n /**\n * 初始化图片处理器\n */\n async initialize(): Promise<void> {\n logger.info('🖼️ [ImageProcessor] 初始化图片处理器...');\n\n try {\n // 尝试加载Sharp库\n try {\n this.sharp = require('sharp');\n logger.info('✅ [ImageProcessor] Sharp库加载成功');\n } catch (error) {\n console.warn('⚠️ [ImageProcessor] Sharp库未安装,使用模拟模式');\n // 创建模拟Sharp对象\n this.sharp = this.createMockSharp();\n }\n\n this.isInitialized = true;\n logger.info('✅ [ImageProcessor] 图片处理器初始化完成');\n } catch (error) {\n console.error('❌ [ImageProcessor] 图片处理器初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 处理图片文件\n */\n async process(\n inputPath: string,\n outputPath: string,\n options: ProcessingOptions\n ): Promise<ProcessingResult> {\n this.ensureInitialized();\n\n if (options.type !== 'image') {\n throw new Error('处理选项类型不匹配:期望 image');\n }\n\n const imageOptions = options as ImageProcessingOptions;\n const startTime = Date.now();\n\n logger.info(`🖼️ [ImageProcessor] 开始处理图片: ${inputPath}`);\n\n try {\n // 检查输入文件是否存在\n if (!existsSync(inputPath)) {\n throw new Error(`输入文件不存在: ${inputPath}`);\n }\n\n // 确保输出目录存在\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n\n // 获取图片元数据\n const metadata = await this.getImageMetadata(inputPath);\n logger.info(\n `📊 [ImageProcessor] 图片信息: ${metadata.width}x${metadata.height}, 格式: ${metadata.format}`\n );\n\n // 创建Sharp处理实例\n let sharpInstance = this.sharp(inputPath);\n\n // 应用图片处理操作\n sharpInstance = await this.applyImageOperations(sharpInstance, imageOptions);\n\n // 确定输出格式\n const outputFormat = this.determineOutputFormat(outputPath, imageOptions.format);\n\n // 应用输出格式和质量设置\n sharpInstance = this.applyOutputSettings(sharpInstance, outputFormat, imageOptions.quality);\n\n // 执行处理并保存\n const info = await sharpInstance.toFile(outputPath);\n\n // 生成缩略图(如果需要)\n let thumbnailPath: string | undefined;\n if (this.shouldGenerateThumbnail(imageOptions)) {\n thumbnailPath = await this.generateThumbnail(inputPath, outputPath, imageOptions);\n }\n\n const processingTime = Date.now() - startTime;\n logger.info(`✅ [ImageProcessor] 图片处理完成: ${outputPath}, 耗时: ${processingTime}ms`);\n\n return {\n success: true,\n processedPath: outputPath,\n processedSize: info.size,\n thumbnailPath,\n processingTime,\n data: {\n originalSize: (await fs.stat(inputPath)).size,\n processedSize: info.size,\n compressionRatio:\n ((await fs.stat(inputPath)).size - info.size) / (await fs.stat(inputPath)).size,\n dimensions: {\n original: { width: metadata.width, height: metadata.height },\n processed: { width: info.width, height: info.height },\n },\n format: {\n original: metadata.format,\n processed: outputFormat,\n },\n },\n };\n } catch (error) {\n console.error(`❌ [ImageProcessor] 图片处理失败: ${inputPath}:`, error);\n\n return {\n success: false,\n error: `图片处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n processingTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * 检查文件是否支持处理\n */\n supports(mimeType: string): boolean {\n const supportedTypes = [\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'image/webp',\n 'image/avif',\n 'image/gif',\n 'image/tiff',\n 'image/bmp',\n ];\n\n return supportedTypes.includes(mimeType.toLowerCase());\n }\n\n /**\n * 获取图片文件信息\n */\n async getFileInfo(filePath: string): Promise<Record<string, any>> {\n this.ensureInitialized();\n\n try {\n const metadata = await this.getImageMetadata(filePath);\n const stats = await fs.stat(filePath);\n\n return {\n dimensions: {\n width: metadata.width,\n height: metadata.height,\n },\n format: metadata.format,\n channels: metadata.channels,\n hasAlpha: metadata.hasAlpha,\n density: metadata.density,\n orientation: metadata.orientation,\n fileSize: stats.size,\n aspectRatio: metadata.width / metadata.height,\n megapixels: (metadata.width * metadata.height) / 1000000,\n };\n } catch (error) {\n console.error(`❌ [ImageProcessor] 获取图片信息失败: ${filePath}:`, error);\n throw error;\n }\n }\n\n // ============= 私有方法 =============\n\n /**\n * 确保处理器已初始化\n */\n private ensureInitialized(): void {\n if (!this.isInitialized || !this.sharp) {\n throw new Error('图片处理器未初始化');\n }\n }\n\n /**\n * 获取图片元数据\n */\n private async getImageMetadata(filePath: string): Promise<ImageMetadata> {\n try {\n const metadata = await this.sharp(filePath).metadata();\n\n return {\n format: metadata.format || 'unknown',\n width: metadata.width || 0,\n height: metadata.height || 0,\n channels: metadata.channels || 3,\n density: metadata.density || 72,\n hasAlpha: metadata.hasAlpha || false,\n orientation: metadata.orientation,\n };\n } catch (error) {\n console.error(`❌ [ImageProcessor] 获取图片元数据失败: ${filePath}:`, error);\n throw new Error(`无法读取图片元数据: ${error instanceof Error ? error.message : '未知错误'}`);\n }\n }\n\n /**\n * 应用图片处理操作\n */\n private async applyImageOperations(\n sharpInstance: any,\n options: ImageProcessingOptions\n ): Promise<any> {\n // 调整尺寸\n if (options.width || options.height) {\n const resizeOptions: any = {\n width: options.width,\n height: options.height,\n fit: 'inside', // 保持纵横比\n withoutEnlargement: true, // 不放大小图片\n };\n\n sharpInstance = sharpInstance.resize(resizeOptions);\n logger.info(\n `🔧 [ImageProcessor] 应用尺寸调整: ${options.width || 'auto'}x${options.height || 'auto'}`\n );\n }\n\n // 旋转和翻转(基于EXIF方向信息)\n sharpInstance = sharpInstance.rotate();\n\n // 添加水印\n if (options.watermark && options.watermarkOptions) {\n sharpInstance = await this.applyWatermark(sharpInstance, options.watermarkOptions);\n }\n\n return sharpInstance;\n }\n\n /**\n * 应用水印\n */\n private async applyWatermark(\n sharpInstance: any,\n watermarkOptions: NonNullable<ImageProcessingOptions['watermarkOptions']>\n ): Promise<any> {\n try {\n if (watermarkOptions.text) {\n // 文字水印\n logger.info(`💧 [ImageProcessor] 应用文字水印: ${watermarkOptions.text}`);\n\n // 创建文字水印SVG\n const textSvg = this.createTextWatermarkSvg(\n watermarkOptions.text,\n watermarkOptions.opacity || 0.5\n );\n\n const textBuffer = Buffer.from(textSvg);\n\n sharpInstance = sharpInstance.composite([\n {\n input: textBuffer,\n gravity: this.getWatermarkGravity(watermarkOptions.position || 'bottom-right'),\n },\n ]);\n } else if (watermarkOptions.image && existsSync(watermarkOptions.image)) {\n // 图片水印\n logger.info(`💧 [ImageProcessor] 应用图片水印: ${watermarkOptions.image}`);\n\n let watermarkBuffer = await fs.readFile(watermarkOptions.image);\n\n // 调整水印透明度\n if (watermarkOptions.opacity && watermarkOptions.opacity < 1) {\n const watermarkSharp = this.sharp(watermarkBuffer)\n .png()\n .modulate({ brightness: 1, saturation: 1, alpha: watermarkOptions.opacity });\n watermarkBuffer = await watermarkSharp.toBuffer();\n }\n\n sharpInstance = sharpInstance.composite([\n {\n input: watermarkBuffer,\n gravity: this.getWatermarkGravity(watermarkOptions.position || 'bottom-right'),\n },\n ]);\n }\n\n return sharpInstance;\n } catch (error) {\n console.warn(`⚠️ [ImageProcessor] 水印应用失败,跳过水印:`, error);\n return sharpInstance;\n }\n }\n\n /**\n * 创建文字水印SVG\n */\n private createTextWatermarkSvg(text: string, opacity: number): string {\n const fontSize = 24;\n const padding = 10;\n\n return `\n <svg width=\"200\" height=\"50\" xmlns=\"http://www.w3.org/2000/svg\">\n <text\n x=\"${padding}\"\n y=\"${fontSize + padding}\"\n font-family=\"Arial, sans-serif\"\n font-size=\"${fontSize}\"\n fill=\"white\"\n fill-opacity=\"${opacity}\"\n stroke=\"black\"\n stroke-width=\"1\"\n stroke-opacity=\"${opacity * 0.8}\"\n >\n ${text}\n </text>\n </svg>\n `.trim();\n }\n\n /**\n * 获取水印位置对应的gravity值\n */\n private getWatermarkGravity(position: string): string {\n const gravityMap: Record<string, string> = {\n 'top-left': 'northwest',\n 'top-right': 'northeast',\n 'bottom-left': 'southwest',\n 'bottom-right': 'southeast',\n center: 'center',\n };\n\n return gravityMap[position] || 'southeast';\n }\n\n /**\n * 确定输出格式\n */\n private determineOutputFormat(\n outputPath: string,\n requestedFormat?: ImageProcessingOptions['format']\n ): string {\n if (requestedFormat) {\n return requestedFormat;\n }\n\n const ext = path.extname(outputPath).toLowerCase();\n const formatMap: Record<string, string> = {\n '.jpg': 'jpeg',\n '.jpeg': 'jpeg',\n '.png': 'png',\n '.webp': 'webp',\n '.avif': 'avif',\n };\n\n return formatMap[ext] || 'jpeg';\n }\n\n /**\n * 应用输出设置\n */\n private applyOutputSettings(sharpInstance: any, format: string, quality?: number): any {\n const defaultQuality = 80;\n const finalQuality = quality || defaultQuality;\n\n switch (format) {\n case 'jpeg':\n return sharpInstance.jpeg({\n quality: finalQuality,\n progressive: true,\n mozjpeg: true,\n });\n\n case 'png':\n return sharpInstance.png({\n quality: finalQuality,\n progressive: true,\n compressionLevel: 6,\n });\n\n case 'webp':\n return sharpInstance.webp({\n quality: finalQuality,\n effort: 4,\n });\n\n case 'avif':\n return sharpInstance.avif({\n quality: finalQuality,\n effort: 4,\n });\n\n default:\n return sharpInstance.jpeg({ quality: finalQuality });\n }\n }\n\n /**\n * 是否需要生成缩略图\n */\n private shouldGenerateThumbnail(options: ImageProcessingOptions): boolean {\n // 如果明确设置了尺寸且尺寸较小,可能不需要缩略图\n const isSmallImage =\n (options.width && options.width <= 300) || (options.height && options.height <= 300);\n\n return !isSmallImage;\n }\n\n /**\n * 生成缩略图\n */\n private async generateThumbnail(\n inputPath: string,\n outputPath: string,\n _options: ImageProcessingOptions\n ): Promise<string> {\n try {\n const thumbnailPath = this.getThumbnailPath(outputPath);\n const thumbnailSize = 200; // 缩略图固定尺寸\n\n await this.sharp(inputPath)\n .resize({\n width: thumbnailSize,\n height: thumbnailSize,\n fit: 'cover',\n position: 'center',\n })\n .jpeg({ quality: 70 })\n .toFile(thumbnailPath);\n\n logger.info(`🖼️ [ImageProcessor] 缩略图生成完成: ${thumbnailPath}`);\n\n return thumbnailPath;\n } catch (error) {\n console.warn(`⚠️ [ImageProcessor] 缩略图生成失败:`, error);\n throw error;\n }\n }\n\n /**\n * 获取缩略图路径\n */\n private getThumbnailPath(originalPath: string): string {\n const ext = path.extname(originalPath);\n const basePath = originalPath.replace(ext, '');\n return `${basePath}_thumb${ext}`;\n }\n\n /**\n * 创建模拟Sharp对象(开发测试用)\n */\n private createMockSharp(): any {\n logger.info('🧪 [ImageProcessor] 创建模拟Sharp处理器');\n\n const mockSharp = (input: string) => {\n logger.info(`🧪 [MockSharp] 处理图片: ${input}`);\n\n return {\n metadata: async () => ({\n format: 'jpeg',\n width: 1920,\n height: 1080,\n channels: 3,\n density: 72,\n hasAlpha: false,\n }),\n\n resize: (options: any) => {\n logger.info(`🧪 [MockSharp] 调整尺寸:`, options);\n return mockSharp(input);\n },\n\n rotate: () => {\n logger.info(`🧪 [MockSharp] 自动旋转`);\n return mockSharp(input);\n },\n\n composite: (operations: any[]) => {\n logger.info(`🧪 [MockSharp] 合成操作:`, operations.length);\n return mockSharp(input);\n },\n\n jpeg: (options: any) => {\n logger.info(`🧪 [MockSharp] JPEG输出:`, options);\n return mockSharp(input);\n },\n\n png: (options: any) => {\n logger.info(`🧪 [MockSharp] PNG输出:`, options);\n return mockSharp(input);\n },\n\n webp: (options: any) => {\n logger.info(`🧪 [MockSharp] WebP输出:`, options);\n return mockSharp(input);\n },\n\n avif: (options: any) => {\n logger.info(`🧪 [MockSharp] AVIF输出:`, options);\n return mockSharp(input);\n },\n\n toFile: async (outputPath: string) => {\n logger.info(`🧪 [MockSharp] 保存到文件: ${outputPath}`);\n\n // 创建一个模拟的输出文件\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n await fs.writeFile(outputPath, `Mock processed image from ${input}`);\n\n return {\n format: 'jpeg',\n width: 800,\n height: 600,\n channels: 3,\n premultiplied: false,\n size: 1024 * 50, // 50KB\n };\n },\n\n toBuffer: async () => {\n logger.info(`🧪 [MockSharp] 转换为Buffer`);\n return Buffer.from('Mock image buffer');\n },\n };\n };\n\n return mockSharp;\n }\n\n /**\n * 批量图片处理\n */\n async batchProcess(\n inputPaths: string[],\n outputDir: string,\n options: ImageProcessingOptions,\n onProgress?: (completed: number, total: number) => void\n ): Promise<ProcessingResult[]> {\n this.ensureInitialized();\n\n logger.info(`🖼️ [ImageProcessor] 开始批量处理 ${inputPaths.length} 张图片`);\n\n const results: ProcessingResult[] = [];\n\n for (let i = 0; i < inputPaths.length; i++) {\n const inputPath = inputPaths[i]!;\n const fileName = path.basename(inputPath);\n const outputPath = path.join(outputDir, fileName);\n\n try {\n const result = await this.process(inputPath, outputPath, options);\n results.push(result);\n\n if (onProgress) {\n onProgress(i + 1, inputPaths.length);\n }\n } catch (error) {\n console.error(`❌ [ImageProcessor] 批量处理失败: ${inputPath}:`, error);\n results.push({\n success: false,\n error: `处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n });\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n logger.info(`✅ [ImageProcessor] 批量处理完成,成功: ${successCount}/${inputPaths.length}`);\n\n return results;\n }\n}\n","/**\n * 音频处理器实现\n * 支持格式转换、压缩、音质调整等功能\n */\n\nimport * as path from 'path';\nimport { promises as fs } from 'fs';\nimport { existsSync } from 'fs';\nimport { createLogger } from '../../../logger';\n\n\nimport type {\n IFileProcessor,\n ProcessorType,\n ProcessingOptions,\n ProcessingResult,\n} from '../types';\n\nimport type { AudioProcessingOptions } from '../../types';\n\nconst logger = createLogger('AudioProcessor');\n\n// 音频处理相关类型定义\ninterface AudioMetadata {\n format: string;\n duration: number;\n bitrate: number;\n sampleRate: number;\n channels: number;\n codec: string;\n size: number;\n}\n\n/**\n * 音频处理器\n * 使用FFmpeg进行音频处理\n */\nexport class AudioProcessor implements IFileProcessor {\n readonly type: ProcessorType = 'audio';\n\n private ffmpeg: any = null;\n private isInitialized = false;\n\n /**\n * 初始化音频处理器\n */\n async initialize(): Promise<void> {\n logger.info('🎵 [AudioProcessor] 初始化音频处理器...');\n\n try {\n // 尝试加载FFmpeg库\n try {\n this.ffmpeg = require('fluent-ffmpeg');\n logger.info('✅ [AudioProcessor] FFmpeg库加载成功');\n } catch (error) {\n console.warn('⚠️ [AudioProcessor] FFmpeg库未安装,使用模拟模式');\n // 创建模拟FFmpeg对象\n this.ffmpeg = this.createMockFFmpeg();\n }\n\n this.isInitialized = true;\n logger.info('✅ [AudioProcessor] 音频处理器初始化完成');\n } catch (error) {\n console.error('❌ [AudioProcessor] 音频处理器初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 处理音频文件\n */\n async process(\n inputPath: string,\n outputPath: string,\n options: ProcessingOptions\n ): Promise<ProcessingResult> {\n this.ensureInitialized();\n\n if (options.type !== 'audio') {\n throw new Error('处理选项类型不匹配:期望 audio');\n }\n\n const audioOptions = options as AudioProcessingOptions;\n const startTime = Date.now();\n\n logger.info(`🎵 [AudioProcessor] 开始处理音频: ${inputPath}`);\n\n try {\n // 检查输入文件是否存在\n if (!existsSync(inputPath)) {\n throw new Error(`输入文件不存在: ${inputPath}`);\n }\n\n // 确保输出目录存在\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n\n // 获取音频元数据\n const metadata = await this.getAudioMetadata(inputPath);\n logger.info(\n `📊 [AudioProcessor] 音频信息: ${this.formatDuration(metadata.duration)}, ${metadata.bitrate}kbps, ${metadata.sampleRate}Hz`\n );\n\n // 确定输出格式\n const outputFormat = this.determineOutputFormat(outputPath, audioOptions.format);\n\n // 执行音频处理\n await this.processAudio(inputPath, outputPath, audioOptions, outputFormat);\n\n // 获取处理后的文件信息\n const processedStats = await fs.stat(outputPath);\n const processingTime = Date.now() - startTime;\n\n logger.info(`✅ [AudioProcessor] 音频处理完成: ${outputPath}, 耗时: ${processingTime}ms`);\n\n return {\n success: true,\n processedPath: outputPath,\n processedSize: processedStats.size,\n processingTime,\n data: {\n originalSize: metadata.size,\n processedSize: processedStats.size,\n compressionRatio: (metadata.size - processedStats.size) / metadata.size,\n duration: metadata.duration,\n originalFormat: metadata.format,\n processedFormat: outputFormat,\n originalBitrate: metadata.bitrate,\n processedBitrate: audioOptions.bitrate || metadata.bitrate,\n sampleRate: audioOptions.sampleRate || metadata.sampleRate,\n channels: audioOptions.channels || metadata.channels,\n },\n };\n } catch (error) {\n console.error(`❌ [AudioProcessor] 音频处理失败: ${inputPath}:`, error);\n\n return {\n success: false,\n error: `音频处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n processingTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * 检查文件是否支持处理\n */\n supports(mimeType: string): boolean {\n const supportedTypes = [\n 'audio/mpeg',\n 'audio/mp3',\n 'audio/wav',\n 'audio/wave',\n 'audio/x-wav',\n 'audio/ogg',\n 'audio/vorbis',\n 'audio/aac',\n 'audio/x-aac',\n 'audio/mp4',\n 'audio/m4a',\n 'audio/flac',\n 'audio/x-flac',\n 'audio/webm',\n 'audio/opus',\n ];\n\n return supportedTypes.includes(mimeType.toLowerCase());\n }\n\n /**\n * 获取音频文件信息\n */\n async getFileInfo(filePath: string): Promise<Record<string, any>> {\n this.ensureInitialized();\n\n try {\n const metadata = await this.getAudioMetadata(filePath);\n\n return {\n duration: metadata.duration,\n durationFormatted: this.formatDuration(metadata.duration),\n bitrate: metadata.bitrate,\n sampleRate: metadata.sampleRate,\n channels: metadata.channels,\n channelsDescription: this.getChannelsDescription(metadata.channels),\n format: metadata.format,\n codec: metadata.codec,\n fileSize: metadata.size,\n quality: this.getQualityDescription(metadata.bitrate, metadata.sampleRate),\n };\n } catch (error) {\n console.error(`❌ [AudioProcessor] 获取音频信息失败: ${filePath}:`, error);\n throw error;\n }\n }\n\n // ============= 私有方法 =============\n\n /**\n * 确保处理器已初始化\n */\n private ensureInitialized(): void {\n if (!this.isInitialized || !this.ffmpeg) {\n throw new Error('音频处理器未初始化');\n }\n }\n\n /**\n * 获取音频元数据\n */\n private async getAudioMetadata(filePath: string): Promise<AudioMetadata> {\n return new Promise((resolve, reject) => {\n try {\n this.ffmpeg.ffprobe(filePath, (err: any, metadata: any) => {\n if (err) {\n console.error(`❌ [AudioProcessor] 获取音频元数据失败: ${filePath}:`, err);\n reject(new Error(`无法读取音频元数据: ${err.message}`));\n return;\n }\n\n const audioStream = metadata.streams?.find(\n (stream: any) => stream.codec_type === 'audio'\n );\n if (!audioStream) {\n reject(new Error('文件中未找到音频流'));\n return;\n }\n\n const result: AudioMetadata = {\n format: metadata.format?.format_name || 'unknown',\n duration: parseFloat(metadata.format?.duration || '0'),\n bitrate: parseInt(audioStream.bit_rate || '0') / 1000, // 转换为kbps\n sampleRate: parseInt(audioStream.sample_rate || '0'),\n channels: parseInt(audioStream.channels || '0'),\n codec: audioStream.codec_name || 'unknown',\n size: parseInt(metadata.format?.size || '0'),\n };\n\n resolve(result);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 执行音频处理\n */\n private async processAudio(\n inputPath: string,\n outputPath: string,\n options: AudioProcessingOptions,\n outputFormat: string\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n let command = this.ffmpeg(inputPath);\n\n // 设置音频编解码器\n command = this.setAudioCodec(command, outputFormat);\n\n // 设置比特率\n if (options.bitrate) {\n command = command.audioBitrate(options.bitrate);\n logger.info(`🔧 [AudioProcessor] 设置比特率: ${options.bitrate}kbps`);\n }\n\n // 设置采样率\n if (options.sampleRate) {\n command = command.audioFrequency(options.sampleRate);\n logger.info(`🔧 [AudioProcessor] 设置采样率: ${options.sampleRate}Hz`);\n }\n\n // 设置声道数\n if (options.channels) {\n command = command.audioChannels(options.channels);\n logger.info(`🔧 [AudioProcessor] 设置声道数: ${options.channels}`);\n }\n\n // 设置输出格式\n command = command.format(outputFormat);\n\n // 添加进度监听\n command.on('progress', (progress: any) => {\n if (progress.percent) {\n logger.info(`🎵 [AudioProcessor] 处理进度: ${Math.round(progress.percent)}%`);\n }\n });\n\n // 添加错误监听\n command.on('error', (err: any) => {\n console.error(`❌ [AudioProcessor] FFmpeg处理错误:`, err);\n reject(new Error(`音频处理失败: ${err.message}`));\n });\n\n // 添加完成监听\n command.on('end', () => {\n logger.info(`✅ [AudioProcessor] FFmpeg处理完成: ${outputPath}`);\n resolve();\n });\n\n // 开始处理\n command.save(outputPath);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 设置音频编解码器\n */\n private setAudioCodec(command: any, format: string): any {\n switch (format) {\n case 'mp3':\n return command.audioCodec('libmp3lame');\n case 'aac':\n return command.audioCodec('aac');\n case 'ogg':\n return command.audioCodec('libvorbis');\n case 'wav':\n return command.audioCodec('pcm_s16le');\n default:\n return command;\n }\n }\n\n /**\n * 确定输出格式\n */\n private determineOutputFormat(\n outputPath: string,\n requestedFormat?: AudioProcessingOptions['format']\n ): string {\n if (requestedFormat) {\n return requestedFormat;\n }\n\n const ext = path.extname(outputPath).toLowerCase();\n const formatMap: Record<string, string> = {\n '.mp3': 'mp3',\n '.wav': 'wav',\n '.ogg': 'ogg',\n '.aac': 'aac',\n '.m4a': 'aac',\n };\n\n return formatMap[ext] || 'mp3';\n }\n\n /**\n * 格式化时长显示\n */\n private formatDuration(seconds: number): string {\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n }\n\n /**\n * 获取声道描述\n */\n private getChannelsDescription(channels: number): string {\n switch (channels) {\n case 1:\n return '单声道';\n case 2:\n return '立体声';\n case 6:\n return '5.1环绕声';\n case 8:\n return '7.1环绕声';\n default:\n return `${channels}声道`;\n }\n }\n\n /**\n * 获取音质描述\n */\n private getQualityDescription(bitrate: number, sampleRate: number): string {\n if (bitrate >= 320 && sampleRate >= 44100) {\n return '高音质';\n } else if (bitrate >= 192 && sampleRate >= 44100) {\n return '标准音质';\n } else if (bitrate >= 128) {\n return '一般音质';\n } else {\n return '低音质';\n }\n }\n\n /**\n * 创建模拟FFmpeg对象(开发测试用)\n */\n private createMockFFmpeg(): any {\n logger.info('🧪 [AudioProcessor] 创建模拟FFmpeg处理器');\n\n const mockFFmpeg = (input: string) => {\n logger.info(`🧪 [MockFFmpeg] 处理音频: ${input}`);\n\n return {\n audioBitrate: (bitrate: number) => {\n logger.info(`🧪 [MockFFmpeg] 设置比特率: ${bitrate}kbps`);\n return mockFFmpeg(input);\n },\n\n audioFrequency: (sampleRate: number) => {\n logger.info(`🧪 [MockFFmpeg] 设置采样率: ${sampleRate}Hz`);\n return mockFFmpeg(input);\n },\n\n audioChannels: (channels: number) => {\n logger.info(`🧪 [MockFFmpeg] 设置声道数: ${channels}`);\n return mockFFmpeg(input);\n },\n\n audioCodec: (codec: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置编解码器: ${codec}`);\n return mockFFmpeg(input);\n },\n\n format: (format: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置输出格式: ${format}`);\n return mockFFmpeg(input);\n },\n\n on: (event: string, callback: Function) => {\n logger.info(`🧪 [MockFFmpeg] 注册事件监听: ${event}`);\n\n if (event === 'progress') {\n // 模拟进度更新\n setTimeout(() => callback({ percent: 50 }), 100);\n setTimeout(() => callback({ percent: 100 }), 200);\n } else if (event === 'end') {\n // 模拟处理完成\n setTimeout(() => callback(), 300);\n }\n\n return mockFFmpeg(input);\n },\n\n save: async (outputPath: string) => {\n logger.info(`🧪 [MockFFmpeg] 保存音频文件: ${outputPath}`);\n\n // 创建模拟输出文件\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n await fs.writeFile(outputPath, `Mock processed audio from ${input}`);\n },\n };\n };\n\n // 添加ffprobe方法\n mockFFmpeg.ffprobe = (filePath: string, callback: Function) => {\n logger.info(`🧪 [MockFFmpeg] 获取音频元数据: ${filePath}`);\n\n setTimeout(() => {\n const mockMetadata = {\n streams: [\n {\n codec_type: 'audio',\n codec_name: 'mp3',\n bit_rate: '128000',\n sample_rate: '44100',\n channels: '2',\n },\n ],\n format: {\n format_name: 'mp3',\n duration: '180.5',\n size: '1024000',\n },\n };\n\n callback(null, mockMetadata);\n }, 100);\n };\n\n return mockFFmpeg;\n }\n\n /**\n * 批量音频处理\n */\n async batchProcess(\n inputPaths: string[],\n outputDir: string,\n options: AudioProcessingOptions,\n onProgress?: (completed: number, total: number) => void\n ): Promise<ProcessingResult[]> {\n this.ensureInitialized();\n\n logger.info(`🎵 [AudioProcessor] 开始批量处理 ${inputPaths.length} 个音频文件`);\n\n const results: ProcessingResult[] = [];\n\n for (let i = 0; i < inputPaths.length; i++) {\n const inputPath = inputPaths[i]!;\n const fileName = path.basename(inputPath);\n const nameWithoutExt = path.parse(fileName).name;\n const outputFormat = options.format || 'mp3';\n const outputPath = path.join(outputDir, `${nameWithoutExt}.${outputFormat}`);\n\n try {\n const result = await this.process(inputPath, outputPath, options);\n results.push(result);\n\n if (onProgress) {\n onProgress(i + 1, inputPaths.length);\n }\n } catch (error) {\n console.error(`❌ [AudioProcessor] 批量处理失败: ${inputPath}:`, error);\n results.push({\n success: false,\n error: `处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n });\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n logger.info(`✅ [AudioProcessor] 批量处理完成,成功: ${successCount}/${inputPaths.length}`);\n\n return results;\n }\n\n /**\n * 提取音频封面\n */\n async extractCover(inputPath: string, outputPath: string): Promise<boolean> {\n this.ensureInitialized();\n\n return new Promise((resolve) => {\n try {\n this.ffmpeg(inputPath)\n .outputOptions(['-an', '-vcodec copy'])\n .on('error', (err: any) => {\n console.warn(`⚠️ [AudioProcessor] 提取封面失败: ${err.message}`);\n resolve(false);\n })\n .on('end', () => {\n logger.info(`🖼️ [AudioProcessor] 音频封面提取完成: ${outputPath}`);\n resolve(true);\n })\n .save(outputPath);\n } catch (error) {\n console.warn(`⚠️ [AudioProcessor] 提取封面异常:`, error);\n resolve(false);\n }\n });\n }\n\n /**\n * 音频降噪处理\n */\n async denoise(inputPath: string, outputPath: string): Promise<ProcessingResult> {\n this.ensureInitialized();\n\n const startTime = Date.now();\n logger.info(`🔇 [AudioProcessor] 开始音频降噪: ${inputPath}`);\n\n return new Promise((resolve) => {\n try {\n this.ffmpeg(inputPath)\n .audioFilters('highpass=f=200,lowpass=f=3000')\n .on('error', (err: any) => {\n resolve({\n success: false,\n error: `降噪处理失败: ${err.message}`,\n processingTime: Date.now() - startTime,\n });\n })\n .on('end', async () => {\n const processedStats = await fs.stat(outputPath);\n\n resolve({\n success: true,\n processedPath: outputPath,\n processedSize: processedStats.size,\n processingTime: Date.now() - startTime,\n data: {\n operation: 'denoise',\n filters: 'highpass=f=200,lowpass=f=3000',\n },\n });\n })\n .save(outputPath);\n } catch (error) {\n resolve({\n success: false,\n error: `降噪处理异常: ${error instanceof Error ? error.message : '未知错误'}`,\n processingTime: Date.now() - startTime,\n });\n }\n });\n }\n}\n","/**\n * 视频处理器实现\n * 支持缩略图生成、格式转换、压缩等功能\n */\n\nimport * as path from 'path';\nimport { promises as fs } from 'fs';\nimport { existsSync } from 'fs';\nimport { createLogger } from '../../../logger';\n\nimport type {\n IFileProcessor,\n ProcessorType,\n ProcessingOptions,\n ProcessingResult,\n} from '../types';\n\nimport type { VideoProcessingOptions } from '../../types';\n\nconst logger = createLogger('VideoProcessor');\n\n// 视频处理相关类型定义\ninterface VideoMetadata {\n format: string;\n duration: number;\n bitrate: number;\n width: number;\n height: number;\n fps: number;\n codec: string;\n size: number;\n aspectRatio: number;\n}\n\n/**\n * 视频处理器\n * 使用FFmpeg进行视频处理\n */\nexport class VideoProcessor implements IFileProcessor {\n readonly type: ProcessorType = 'video';\n\n private ffmpeg: any = null;\n private isInitialized = false;\n\n /**\n * 初始化视频处理器\n */\n async initialize(): Promise<void> {\n logger.info('🎬 [VideoProcessor] 初始化视频处理器...');\n\n try {\n // 尝试加载FFmpeg库\n try {\n this.ffmpeg = require('fluent-ffmpeg');\n logger.info('✅ [VideoProcessor] FFmpeg库加载成功');\n } catch (error) {\n console.warn('⚠️ [VideoProcessor] FFmpeg库未安装,使用模拟模式');\n // 创建模拟FFmpeg对象\n this.ffmpeg = this.createMockFFmpeg();\n }\n\n this.isInitialized = true;\n logger.info('✅ [VideoProcessor] 视频处理器初始化完成');\n } catch (error) {\n console.error('❌ [VideoProcessor] 视频处理器初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 处理视频文件\n */\n async process(\n inputPath: string,\n outputPath: string,\n options: ProcessingOptions\n ): Promise<ProcessingResult> {\n this.ensureInitialized();\n\n if (options.type !== 'video') {\n throw new Error('处理选项类型不匹配:期望 video');\n }\n\n const videoOptions = options as VideoProcessingOptions;\n const startTime = Date.now();\n\n logger.info(`🎬 [VideoProcessor] 开始处理视频: ${inputPath}`);\n\n try {\n // 检查输入文件是否存在\n if (!existsSync(inputPath)) {\n throw new Error(`输入文件不存在: ${inputPath}`);\n }\n\n // 确保输出目录存在\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n\n // 获取视频元数据\n const metadata = await this.getVideoMetadata(inputPath);\n logger.info(\n `📊 [VideoProcessor] 视频信息: ${metadata.width}x${metadata.height}, ${this.formatDuration(metadata.duration)}, ${metadata.fps}fps`\n );\n\n // 确定输出格式\n const outputFormat = this.determineOutputFormat(outputPath, videoOptions.format);\n\n // 执行视频处理\n await this.processVideo(inputPath, outputPath, videoOptions, outputFormat);\n\n // 生成缩略图(如果需要)\n let thumbnailPath: string | undefined;\n if (videoOptions.generateThumbnail !== false) {\n thumbnailPath = await this.generateThumbnail(\n inputPath,\n outputPath,\n videoOptions.thumbnailTime || 1\n );\n }\n\n // 获取处理后的文件信息\n const processedStats = await fs.stat(outputPath);\n const processingTime = Date.now() - startTime;\n\n logger.info(`✅ [VideoProcessor] 视频处理完成: ${outputPath}, 耗时: ${processingTime}ms`);\n\n return {\n success: true,\n processedPath: outputPath,\n processedSize: processedStats.size,\n thumbnailPath,\n processingTime,\n data: {\n originalSize: metadata.size,\n processedSize: processedStats.size,\n compressionRatio: (metadata.size - processedStats.size) / metadata.size,\n duration: metadata.duration,\n originalFormat: metadata.format,\n processedFormat: outputFormat,\n dimensions: {\n original: { width: metadata.width, height: metadata.height },\n processed: { width: metadata.width, height: metadata.height }, // 处理后可能会变化\n },\n fps: metadata.fps,\n bitrate: metadata.bitrate,\n },\n };\n } catch (error) {\n console.error(`❌ [VideoProcessor] 视频处理失败: ${inputPath}:`, error);\n\n return {\n success: false,\n error: `视频处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n processingTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * 检查文件是否支持处理\n */\n supports(mimeType: string): boolean {\n const supportedTypes = [\n 'video/mp4',\n 'video/x-msvideo', // avi\n 'video/quicktime', // mov\n 'video/x-ms-wmv', // wmv\n 'video/webm',\n 'video/ogg',\n 'video/3gpp', // 3gp\n 'video/x-flv', // flv\n 'video/x-matroska', // mkv\n ];\n\n return supportedTypes.includes(mimeType.toLowerCase());\n }\n\n /**\n * 获取视频文件信息\n */\n async getFileInfo(filePath: string): Promise<Record<string, any>> {\n this.ensureInitialized();\n\n try {\n const metadata = await this.getVideoMetadata(filePath);\n\n return {\n duration: metadata.duration,\n durationFormatted: this.formatDuration(metadata.duration),\n dimensions: {\n width: metadata.width,\n height: metadata.height,\n },\n resolution: this.getResolutionDescription(metadata.width, metadata.height),\n aspectRatio: metadata.aspectRatio,\n fps: metadata.fps,\n bitrate: metadata.bitrate,\n format: metadata.format,\n codec: metadata.codec,\n fileSize: metadata.size,\n quality: this.getQualityDescription(metadata.width, metadata.height, metadata.bitrate),\n };\n } catch (error) {\n console.error(`❌ [VideoProcessor] 获取视频信息失败: ${filePath}:`, error);\n throw error;\n }\n }\n\n // ============= 私有方法 =============\n\n /**\n * 确保处理器已初始化\n */\n private ensureInitialized(): void {\n if (!this.isInitialized || !this.ffmpeg) {\n throw new Error('视频处理器未初始化');\n }\n }\n\n /**\n * 获取视频元数据\n */\n private async getVideoMetadata(filePath: string): Promise<VideoMetadata> {\n return new Promise((resolve, reject) => {\n try {\n this.ffmpeg.ffprobe(filePath, (err: any, metadata: any) => {\n if (err) {\n console.error(`❌ [VideoProcessor] 获取视频元数据失败: ${filePath}:`, err);\n reject(new Error(`无法读取视频元数据: ${err.message}`));\n return;\n }\n\n const videoStream = metadata.streams?.find(\n (stream: any) => stream.codec_type === 'video'\n );\n if (!videoStream) {\n reject(new Error('文件中未找到视频流'));\n return;\n }\n\n const width = parseInt(videoStream.width || '0');\n const height = parseInt(videoStream.height || '0');\n\n const result: VideoMetadata = {\n format: metadata.format?.format_name || 'unknown',\n duration: parseFloat(metadata.format?.duration || '0'),\n bitrate: parseInt(metadata.format?.bit_rate || '0') / 1000, // 转换为kbps\n width,\n height,\n fps: this.parseFPS(videoStream.r_frame_rate || '0/1'),\n codec: videoStream.codec_name || 'unknown',\n size: parseInt(metadata.format?.size || '0'),\n aspectRatio: width > 0 && height > 0 ? width / height : 16 / 9,\n };\n\n resolve(result);\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 解析帧率\n */\n private parseFPS(frameRate: string): number {\n const parts = frameRate.split('/').map(Number);\n const numerator = parts[0] || 0;\n const denominator = parts[1] || 1;\n return denominator > 0 ? numerator / denominator : 0;\n }\n\n /**\n * 执行视频处理\n */\n private async processVideo(\n inputPath: string,\n outputPath: string,\n options: VideoProcessingOptions,\n outputFormat: string\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n let command = this.ffmpeg(inputPath);\n\n // 设置视频编解码器\n command = this.setVideoCodec(command, outputFormat);\n\n // 设置质量\n if (options.quality) {\n command = this.setVideoQuality(command, options.quality);\n logger.info(`🔧 [VideoProcessor] 设置视频质量: ${options.quality}`);\n }\n\n // 设置输出格式\n command = command.format(outputFormat);\n\n // 添加进度监听\n command.on('progress', (progress: any) => {\n if (progress.percent) {\n logger.info(`🎬 [VideoProcessor] 处理进度: ${Math.round(progress.percent)}%`);\n }\n });\n\n // 添加错误监听\n command.on('error', (err: any) => {\n console.error(`❌ [VideoProcessor] FFmpeg处理错误:`, err);\n reject(new Error(`视频处理失败: ${err.message}`));\n });\n\n // 添加完成监听\n command.on('end', () => {\n logger.info(`✅ [VideoProcessor] FFmpeg处理完成: ${outputPath}`);\n resolve();\n });\n\n // 开始处理\n command.save(outputPath);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 设置视频编解码器\n */\n private setVideoCodec(command: any, format: string): any {\n switch (format) {\n case 'mp4':\n return command.videoCodec('libx264').audioCodec('aac');\n case 'webm':\n return command.videoCodec('libvpx-vp9').audioCodec('libvorbis');\n case 'avi':\n return command.videoCodec('libx264').audioCodec('mp3');\n case 'mov':\n return command.videoCodec('libx264').audioCodec('aac');\n default:\n return command.videoCodec('libx264').audioCodec('aac');\n }\n }\n\n /**\n * 设置视频质量\n */\n private setVideoQuality(command: any, quality: number): any {\n // 质量范围:1-100,值越高质量越好\n const crf = Math.max(18, Math.min(51, 51 - Math.floor(quality * 0.33))); // 将1-100映射到51-18\n return command.outputOptions([`-crf ${crf}`]);\n }\n\n /**\n * 确定输出格式\n */\n private determineOutputFormat(\n outputPath: string,\n requestedFormat?: VideoProcessingOptions['format']\n ): string {\n if (requestedFormat) {\n return requestedFormat;\n }\n\n const ext = path.extname(outputPath).toLowerCase();\n const formatMap: Record<string, string> = {\n '.mp4': 'mp4',\n '.avi': 'avi',\n '.mov': 'mov',\n '.webm': 'webm',\n };\n\n return formatMap[ext] || 'mp4';\n }\n\n /**\n * 生成缩略图\n */\n private async generateThumbnail(\n inputPath: string,\n outputPath: string,\n timeOffset: number\n ): Promise<string> {\n return new Promise((resolve, reject) => {\n try {\n const thumbnailPath = this.getThumbnailPath(outputPath);\n\n this.ffmpeg(inputPath)\n .seekInput(timeOffset)\n .frames(1)\n .size('320x240')\n .on('error', (err: any) => {\n console.warn(`⚠️ [VideoProcessor] 缩略图生成失败: ${err.message}`);\n reject(err);\n })\n .on('end', () => {\n logger.info(`🖼️ [VideoProcessor] 视频缩略图生成完成: ${thumbnailPath}`);\n resolve(thumbnailPath);\n })\n .save(thumbnailPath);\n } catch (error) {\n console.warn(`⚠️ [VideoProcessor] 缩略图生成异常:`, error);\n reject(error);\n }\n });\n }\n\n /**\n * 获取缩略图路径\n */\n private getThumbnailPath(originalPath: string): string {\n const ext = path.extname(originalPath);\n const basePath = originalPath.replace(ext, '');\n return `${basePath}_thumb.jpg`;\n }\n\n /**\n * 格式化时长显示\n */\n private formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const remainingSeconds = Math.floor(seconds % 60);\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;\n } else {\n return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;\n }\n }\n\n /**\n * 获取分辨率描述\n */\n private getResolutionDescription(width: number, height: number): string {\n if (width >= 3840 && height >= 2160) {\n return '4K UHD';\n } else if (width >= 1920 && height >= 1080) {\n return '1080p Full HD';\n } else if (width >= 1280 && height >= 720) {\n return '720p HD';\n } else if (width >= 640 && height >= 480) {\n return '480p SD';\n } else {\n return `${width}x${height}`;\n }\n }\n\n /**\n * 获取视频质量描述\n */\n private getQualityDescription(width: number, height: number, bitrate: number): string {\n const pixels = width * height;\n const bitratePerPixel = (bitrate / pixels) * 1000; // 每像素比特率\n\n if (pixels >= 1920 * 1080 && bitratePerPixel >= 0.1) {\n return '高清';\n } else if (pixels >= 1280 * 720 && bitratePerPixel >= 0.05) {\n return '标清';\n } else if (bitratePerPixel >= 0.02) {\n return '一般';\n } else {\n return '低质量';\n }\n }\n\n /**\n * 创建模拟FFmpeg对象(开发测试用)\n */\n private createMockFFmpeg(): any {\n logger.info('🧪 [VideoProcessor] 创建模拟FFmpeg处理器');\n\n const mockFFmpeg = (input: string) => {\n logger.info(`🧪 [MockFFmpeg] 处理视频: ${input}`);\n\n return {\n videoCodec: (codec: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置视频编解码器: ${codec}`);\n return mockFFmpeg(input);\n },\n\n audioCodec: (codec: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置音频编解码器: ${codec}`);\n return mockFFmpeg(input);\n },\n\n format: (format: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置输出格式: ${format}`);\n return mockFFmpeg(input);\n },\n\n outputOptions: (options: string[]) => {\n logger.info(`🧪 [MockFFmpeg] 设置输出选项:`, options);\n return mockFFmpeg(input);\n },\n\n seekInput: (time: number) => {\n logger.info(`🧪 [MockFFmpeg] 跳转到时间: ${time}s`);\n return mockFFmpeg(input);\n },\n\n frames: (count: number) => {\n logger.info(`🧪 [MockFFmpeg] 提取帧数: ${count}`);\n return mockFFmpeg(input);\n },\n\n size: (size: string) => {\n logger.info(`🧪 [MockFFmpeg] 设置尺寸: ${size}`);\n return mockFFmpeg(input);\n },\n\n on: (event: string, callback: Function) => {\n logger.info(`🧪 [MockFFmpeg] 注册事件监听: ${event}`);\n\n if (event === 'progress') {\n // 模拟进度更新\n setTimeout(() => callback({ percent: 25 }), 100);\n setTimeout(() => callback({ percent: 50 }), 200);\n setTimeout(() => callback({ percent: 75 }), 300);\n setTimeout(() => callback({ percent: 100 }), 400);\n } else if (event === 'end') {\n // 模拟处理完成\n setTimeout(() => callback(), 500);\n }\n\n return mockFFmpeg(input);\n },\n\n save: async (outputPath: string) => {\n logger.info(`🧪 [MockFFmpeg] 保存视频文件: ${outputPath}`);\n\n // 创建模拟输出文件\n const outputDir = path.dirname(outputPath);\n await fs.mkdir(outputDir, { recursive: true });\n await fs.writeFile(outputPath, `Mock processed video from ${input}`);\n },\n };\n };\n\n // 添加ffprobe方法\n mockFFmpeg.ffprobe = (filePath: string, callback: Function) => {\n logger.info(`🧪 [MockFFmpeg] 获取视频元数据: ${filePath}`);\n\n setTimeout(() => {\n const mockMetadata = {\n streams: [\n {\n codec_type: 'video',\n codec_name: 'h264',\n width: '1920',\n height: '1080',\n r_frame_rate: '30/1',\n },\n ],\n format: {\n format_name: 'mp4',\n duration: '300.0',\n size: '50000000',\n bit_rate: '1000000',\n },\n };\n\n callback(null, mockMetadata);\n }, 100);\n };\n\n return mockFFmpeg;\n }\n\n /**\n * 批量视频处理\n */\n async batchProcess(\n inputPaths: string[],\n outputDir: string,\n options: VideoProcessingOptions,\n onProgress?: (completed: number, total: number) => void\n ): Promise<ProcessingResult[]> {\n this.ensureInitialized();\n\n logger.info(`🎬 [VideoProcessor] 开始批量处理 ${inputPaths.length} 个视频文件`);\n\n const results: ProcessingResult[] = [];\n\n for (let i = 0; i < inputPaths.length; i++) {\n const inputPath = inputPaths[i]!;\n const fileName = path.basename(inputPath);\n const nameWithoutExt = path.parse(fileName).name;\n const outputFormat = options.format || 'mp4';\n const outputPath = path.join(outputDir, `${nameWithoutExt}.${outputFormat}`);\n\n try {\n const result = await this.process(inputPath, outputPath, options);\n results.push(result);\n\n if (onProgress) {\n onProgress(i + 1, inputPaths.length);\n }\n } catch (error) {\n console.error(`❌ [VideoProcessor] 批量处理失败: ${inputPath}:`, error);\n results.push({\n success: false,\n error: `处理失败: ${error instanceof Error ? error.message : '未知错误'}`,\n });\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n logger.info(`✅ [VideoProcessor] 批量处理完成,成功: ${successCount}/${inputPaths.length}`);\n\n return results;\n }\n\n /**\n * 提取视频帧\n */\n async extractFrames(\n inputPath: string,\n outputDir: string,\n options: {\n count?: number;\n interval?: number;\n format?: 'jpg' | 'png';\n } = {}\n ): Promise<string[]> {\n this.ensureInitialized();\n\n const { count = 10, interval, format = 'jpg' } = options;\n\n logger.info(`🖼️ [VideoProcessor] 提取视频帧: ${inputPath}, 数量: ${count}`);\n\n return new Promise((resolve, reject) => {\n try {\n let command = this.ffmpeg(inputPath);\n\n if (interval) {\n // 按间隔提取\n command = command.outputOptions([`-vf fps=1/${interval}`]);\n } else {\n // 按数量提取\n command = command.frames(count);\n }\n\n const outputPattern = path.join(outputDir, `frame_%03d.${format}`);\n\n command\n .on('error', (err: any) => {\n console.error(`❌ [VideoProcessor] 提取帧失败:`, err);\n reject(new Error(`提取帧失败: ${err.message}`));\n })\n .on('end', async () => {\n // 查找生成的帧文件\n try {\n const files = await fs.readdir(outputDir);\n const frameFiles = files\n .filter((file) => file.startsWith('frame_') && file.endsWith(`.${format}`))\n .sort()\n .map((file) => path.join(outputDir, file));\n\n logger.info(`✅ [VideoProcessor] 帧提取完成,共 ${frameFiles.length} 帧`);\n resolve(frameFiles);\n } catch (error) {\n reject(error);\n }\n })\n .save(outputPattern);\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * 视频压缩\n */\n async compress(\n inputPath: string,\n outputPath: string,\n compressionLevel: 'low' | 'medium' | 'high' = 'medium'\n ): Promise<ProcessingResult> {\n this.ensureInitialized();\n\n logger.info(`🗜️ [VideoProcessor] 开始视频压缩: ${inputPath}, 级别: ${compressionLevel}`);\n\n const options: VideoProcessingOptions = {\n type: 'video',\n quality: this.getCompressionQuality(compressionLevel),\n format: 'mp4',\n };\n\n return this.process(inputPath, outputPath, options);\n }\n\n /**\n * 获取压缩质量\n */\n private getCompressionQuality(level: 'low' | 'medium' | 'high'): number {\n switch (level) {\n case 'low':\n return 30;\n case 'medium':\n return 60;\n case 'high':\n return 85;\n default:\n return 60;\n }\n }\n}\n","/**\n * 文件处理队列管理系统\n * 支持异步任务调度、优先级排序、并发控制等功能\n */\n\nimport { EventEmitter } from 'events';\nimport { createLogger } from '../../../logger';\nimport type { IFileProcessor, ProcessingOptions, ProcessingResult, ProcessorType } from '../types';\n\nconst logger = createLogger('ProcessingQueue');\n\n// 队列任务相关类型定义\nexport interface QueueTask {\n id: string;\n inputPath: string;\n outputPath: string;\n options: ProcessingOptions;\n priority: TaskPriority;\n status: TaskStatus;\n processor?: IFileProcessor;\n startTime?: number;\n endTime?: number;\n result?: ProcessingResult;\n error?: string;\n retries: number;\n maxRetries: number;\n onProgress?: (task: QueueTask, progress: number) => void;\n onComplete?: (task: QueueTask, result: ProcessingResult) => void;\n onError?: (task: QueueTask, error: string) => void;\n}\n\nexport type TaskPriority = 'low' | 'normal' | 'high' | 'urgent';\nexport type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';\n\nexport interface QueueOptions {\n maxConcurrentTasks?: number;\n maxRetries?: number;\n retryDelay?: number;\n taskTimeout?: number;\n autoStart?: boolean;\n}\n\nexport interface QueueStats {\n totalTasks: number;\n pendingTasks: number;\n runningTasks: number;\n completedTasks: number;\n failedTasks: number;\n cancelledTasks: number;\n averageProcessingTime: number;\n successRate: number;\n}\n\n/**\n * 文件处理队列管理器\n */\nexport class ProcessingQueue extends EventEmitter {\n private tasks: Map<string, QueueTask> = new Map();\n private runningTasks: Set<string> = new Set();\n private processors: Map<ProcessorType, IFileProcessor> = new Map();\n\n private options: Required<QueueOptions>;\n private isStarted = false;\n private processInterval: NodeJS.Timeout | null = null;\n\n constructor(options: QueueOptions = {}) {\n super();\n\n this.options = {\n maxConcurrentTasks: options.maxConcurrentTasks || 3,\n maxRetries: options.maxRetries || 2,\n retryDelay: options.retryDelay || 5000,\n taskTimeout: options.taskTimeout || 300000, // 5分钟\n autoStart: options.autoStart !== false,\n };\n\n logger.info('📋 [ProcessingQueue] 队列管理器已创建');\n\n if (this.options.autoStart) {\n this.start();\n }\n }\n\n /**\n * 注册文件处理器\n */\n registerProcessor(processor: IFileProcessor): void {\n this.processors.set(processor.type, processor);\n logger.info(`🔧 [ProcessingQueue] 注册处理器: ${processor.type}`);\n }\n\n /**\n * 添加任务到队列\n */\n addTask(\n inputPath: string,\n outputPath: string,\n options: ProcessingOptions,\n taskOptions: Partial<\n Pick<QueueTask, 'priority' | 'maxRetries' | 'onProgress' | 'onComplete' | 'onError'>\n > = {}\n ): string {\n const taskId = this.generateTaskId();\n\n const task: QueueTask = {\n id: taskId,\n inputPath,\n outputPath,\n options,\n priority: taskOptions.priority || 'normal',\n status: 'pending',\n retries: 0,\n maxRetries: taskOptions.maxRetries || this.options.maxRetries,\n onProgress: taskOptions.onProgress,\n onComplete: taskOptions.onComplete,\n onError: taskOptions.onError,\n };\n\n // 获取对应的处理器\n const processor = this.processors.get(options.type);\n if (!processor) {\n throw new Error(`未找到类型为 ${options.type} 的文件处理器`);\n }\n task.processor = processor;\n\n this.tasks.set(taskId, task);\n\n logger.info(`📝 [ProcessingQueue] 添加任务: ${taskId} (${inputPath})`);\n\n this.emit('taskAdded', task);\n\n // 如果队列已启动,尝试立即处理\n if (this.isStarted) {\n this.processNext();\n }\n\n return taskId;\n }\n\n /**\n * 启动队列处理\n */\n start(): void {\n if (this.isStarted) {\n console.warn('⚠️ [ProcessingQueue] 队列已经启动');\n return;\n }\n\n this.isStarted = true;\n logger.info('▶️ [ProcessingQueue] 启动队列处理');\n\n // 定期检查并处理任务\n this.processInterval = setInterval(() => {\n this.processNext();\n }, 1000);\n\n this.emit('started');\n\n // 立即尝试处理任务\n this.processNext();\n }\n\n /**\n * 停止队列处理\n */\n stop(): void {\n if (!this.isStarted) {\n console.warn('⚠️ [ProcessingQueue] 队列未启动');\n return;\n }\n\n this.isStarted = false;\n\n if (this.processInterval) {\n clearInterval(this.processInterval);\n this.processInterval = null;\n }\n\n logger.info('⏹️ [ProcessingQueue] 停止队列处理');\n this.emit('stopped');\n }\n\n /**\n * 暂停任务\n */\n pauseTask(taskId: string): boolean {\n const task = this.tasks.get(taskId);\n if (!task) {\n console.warn(`⚠️ [ProcessingQueue] 任务不存在: ${taskId}`);\n return false;\n }\n\n if (task.status === 'running') {\n console.warn(`⚠️ [ProcessingQueue] 无法暂停正在运行的任务: ${taskId}`);\n return false;\n }\n\n task.status = 'cancelled';\n logger.info(`⏸️ [ProcessingQueue] 暂停任务: ${taskId}`);\n\n this.emit('taskCancelled', task);\n return true;\n }\n\n /**\n * 取消任务\n */\n cancelTask(taskId: string): boolean {\n const task = this.tasks.get(taskId);\n if (!task) {\n console.warn(`⚠️ [ProcessingQueue] 任务不存在: ${taskId}`);\n return false;\n }\n\n if (task.status === 'running') {\n console.warn(`⚠️ [ProcessingQueue] 无法取消正在运行的任务: ${taskId}`);\n return false;\n }\n\n task.status = 'cancelled';\n logger.info(`❌ [ProcessingQueue] 取消任务: ${taskId}`);\n\n this.emit('taskCancelled', task);\n return true;\n }\n\n /**\n * 获取任务状态\n */\n getTask(taskId: string): QueueTask | undefined {\n return this.tasks.get(taskId);\n }\n\n /**\n * 获取所有任务\n */\n getAllTasks(): QueueTask[] {\n return Array.from(this.tasks.values());\n }\n\n /**\n * 获取待处理任务\n */\n getPendingTasks(): QueueTask[] {\n return Array.from(this.tasks.values()).filter((task) => task.status === 'pending');\n }\n\n /**\n * 获取正在运行的任务\n */\n getRunningTasks(): QueueTask[] {\n return Array.from(this.tasks.values()).filter((task) => task.status === 'running');\n }\n\n /**\n * 获取队列统计信息\n */\n getStats(): QueueStats {\n const allTasks = Array.from(this.tasks.values());\n const completedTasks = allTasks.filter((task) => task.status === 'completed');\n\n const totalProcessingTime = completedTasks.reduce((sum, task) => {\n if (task.startTime && task.endTime) {\n return sum + (task.endTime - task.startTime);\n }\n return sum;\n }, 0);\n\n return {\n totalTasks: allTasks.length,\n pendingTasks: allTasks.filter((task) => task.status === 'pending').length,\n runningTasks: allTasks.filter((task) => task.status === 'running').length,\n completedTasks: allTasks.filter((task) => task.status === 'completed').length,\n failedTasks: allTasks.filter((task) => task.status === 'failed').length,\n cancelledTasks: allTasks.filter((task) => task.status === 'cancelled').length,\n averageProcessingTime:\n completedTasks.length > 0 ? totalProcessingTime / completedTasks.length : 0,\n successRate: allTasks.length > 0 ? completedTasks.length / allTasks.length : 0,\n };\n }\n\n /**\n * 清理已完成的任务\n */\n cleanup(): void {\n const beforeCount = this.tasks.size;\n\n for (const [taskId, task] of Array.from(this.tasks.entries())) {\n if (task.status === 'completed' || task.status === 'failed' || task.status === 'cancelled') {\n this.tasks.delete(taskId);\n }\n }\n\n const afterCount = this.tasks.size;\n const cleanedCount = beforeCount - afterCount;\n\n logger.info(`🧹 [ProcessingQueue] 清理完成,移除 ${cleanedCount} 个任务`);\n this.emit('cleanup', { cleaned: cleanedCount, remaining: afterCount });\n }\n\n // ============= 私有方法 =============\n\n /**\n * 处理下一个任务\n */\n private async processNext(): Promise<void> {\n if (!this.isStarted) {\n return;\n }\n\n // 检查并发限制\n if (this.runningTasks.size >= this.options.maxConcurrentTasks) {\n return;\n }\n\n // 获取下一个待处理任务\n const nextTask = this.getNextTask();\n if (!nextTask) {\n return;\n }\n\n // 开始处理任务\n await this.processTask(nextTask);\n }\n\n /**\n * 获取下一个待处理任务(按优先级排序)\n */\n private getNextTask(): QueueTask | null {\n const pendingTasks = this.getPendingTasks();\n if (pendingTasks.length === 0) {\n return null;\n }\n\n // 按优先级排序\n const priorityOrder: Record<TaskPriority, number> = {\n urgent: 4,\n high: 3,\n normal: 2,\n low: 1,\n };\n\n pendingTasks.sort((a, b) => {\n const priorityDiff = priorityOrder[b.priority] - priorityOrder[a.priority];\n if (priorityDiff !== 0) {\n return priorityDiff;\n }\n // 相同优先级按添加时间排序(FIFO)\n return 0;\n });\n\n return pendingTasks[0] || null;\n }\n\n /**\n * 处理单个任务\n */\n private async processTask(task: QueueTask): Promise<void> {\n if (!task.processor) {\n this.failTask(task, '未找到对应的文件处理器');\n return;\n }\n\n logger.info(`🚀 [ProcessingQueue] 开始处理任务: ${task.id}`);\n\n // 更新任务状态\n task.status = 'running';\n task.startTime = Date.now();\n this.runningTasks.add(task.id);\n\n this.emit('taskStarted', task);\n\n // 设置超时\n const timeoutId = setTimeout(() => {\n if (task.status === 'running') {\n this.failTask(task, '任务处理超时');\n }\n }, this.options.taskTimeout);\n\n try {\n // 执行处理\n const result = await task.processor.process(task.inputPath, task.outputPath, task.options);\n\n clearTimeout(timeoutId);\n\n if (result.success) {\n this.completeTask(task, result);\n } else {\n this.retryOrFailTask(task, result.error || '处理失败');\n }\n } catch (error) {\n clearTimeout(timeoutId);\n const errorMessage = error instanceof Error ? error.message : '未知错误';\n this.retryOrFailTask(task, errorMessage);\n }\n }\n\n /**\n * 完成任务\n */\n private completeTask(task: QueueTask, result: ProcessingResult): void {\n task.status = 'completed';\n task.endTime = Date.now();\n task.result = result;\n\n this.runningTasks.delete(task.id);\n\n logger.info(`✅ [ProcessingQueue] 任务完成: ${task.id}`);\n\n if (task.onComplete) {\n try {\n task.onComplete(task, result);\n } catch (error) {\n console.error('❌ [ProcessingQueue] 任务完成回调错误:', error);\n }\n }\n\n this.emit('taskCompleted', task, result);\n\n // 尝试处理下一个任务\n setTimeout(() => this.processNext(), 0);\n }\n\n /**\n * 重试或失败任务\n */\n private retryOrFailTask(task: QueueTask, error: string): void {\n this.runningTasks.delete(task.id);\n\n if (task.retries < task.maxRetries) {\n // 重试任务\n task.retries++;\n task.status = 'pending';\n task.error = undefined;\n\n logger.info(`🔄 [ProcessingQueue] 重试任务: ${task.id} (${task.retries}/${task.maxRetries})`);\n\n this.emit('taskRetried', task);\n\n // 延迟重试\n setTimeout(() => {\n if (this.isStarted) {\n this.processNext();\n }\n }, this.options.retryDelay);\n } else {\n // 任务失败\n this.failTask(task, error);\n }\n }\n\n /**\n * 失败任务\n */\n private failTask(task: QueueTask, error: string): void {\n task.status = 'failed';\n task.endTime = Date.now();\n task.error = error;\n\n this.runningTasks.delete(task.id);\n\n console.error(`❌ [ProcessingQueue] 任务失败: ${task.id} - ${error}`);\n\n if (task.onError) {\n try {\n task.onError(task, error);\n } catch (callbackError) {\n console.error('❌ [ProcessingQueue] 任务失败回调错误:', callbackError);\n }\n }\n\n this.emit('taskFailed', task, error);\n\n // 尝试处理下一个任务\n setTimeout(() => this.processNext(), 0);\n }\n\n /**\n * 生成唯一任务ID\n */\n private generateTaskId(): string {\n return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * 批量添加任务\n */\n addBatchTasks(\n tasks: Array<{\n inputPath: string;\n outputPath: string;\n options: ProcessingOptions;\n priority?: TaskPriority;\n }>,\n onBatchProgress?: (completed: number, total: number) => void,\n onBatchComplete?: (results: Map<string, ProcessingResult>) => void\n ): string[] {\n const taskIds: string[] = [];\n const results = new Map<string, ProcessingResult>();\n let completedCount = 0;\n\n logger.info(`📦 [ProcessingQueue] 批量添加 ${tasks.length} 个任务`);\n\n for (const taskSpec of tasks) {\n const taskId = this.addTask(taskSpec.inputPath, taskSpec.outputPath, taskSpec.options, {\n priority: taskSpec.priority,\n onComplete: (task, result) => {\n results.set(task.id, result);\n completedCount++;\n\n if (onBatchProgress) {\n onBatchProgress(completedCount, tasks.length);\n }\n\n if (completedCount === tasks.length && onBatchComplete) {\n onBatchComplete(results);\n }\n },\n onError: (task, error) => {\n results.set(task.id, { success: false, error });\n completedCount++;\n\n if (onBatchProgress) {\n onBatchProgress(completedCount, tasks.length);\n }\n\n if (completedCount === tasks.length && onBatchComplete) {\n onBatchComplete(results);\n }\n },\n });\n\n taskIds.push(taskId);\n }\n\n return taskIds;\n }\n\n /**\n * 获取队列健康状态\n */\n getHealthStatus(): {\n isHealthy: boolean;\n issues: string[];\n recommendations: string[];\n } {\n const stats = this.getStats();\n const issues: string[] = [];\n const recommendations: string[] = [];\n\n // 检查成功率\n if (stats.successRate < 0.8 && stats.totalTasks > 10) {\n issues.push(`成功率过低: ${(stats.successRate * 100).toFixed(1)}%`);\n recommendations.push('检查文件处理器配置和输入文件质量');\n }\n\n // 检查待处理任务积压\n if (stats.pendingTasks > 50) {\n issues.push(`待处理任务积压: ${stats.pendingTasks} 个`);\n recommendations.push('考虑增加并发处理数或优化处理性能');\n }\n\n // 检查平均处理时间\n if (stats.averageProcessingTime > 60000) {\n // 超过1分钟\n issues.push(`平均处理时间过长: ${(stats.averageProcessingTime / 1000).toFixed(1)}秒`);\n recommendations.push('优化文件处理逻辑或减少处理复杂度');\n }\n\n return {\n isHealthy: issues.length === 0,\n issues,\n recommendations,\n };\n }\n}\n","/**\n * MIME 类型工具函数\n */\n\nimport * as path from 'path';\n\n/** MIME 类型映射表 */\nconst MIME_TYPES: Record<string, string> = {\n // 图片\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.png': 'image/png',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.svg': 'image/svg+xml',\n '.bmp': 'image/bmp',\n '.ico': 'image/x-icon',\n\n // 视频\n '.mp4': 'video/mp4',\n '.avi': 'video/x-msvideo',\n '.mov': 'video/quicktime',\n '.wmv': 'video/x-ms-wmv',\n '.flv': 'video/x-flv',\n '.mkv': 'video/x-matroska',\n '.webm': 'video/webm',\n\n // 音频\n '.mp3': 'audio/mpeg',\n '.wav': 'audio/wav',\n '.ogg': 'audio/ogg',\n '.m4a': 'audio/mp4',\n '.flac': 'audio/flac',\n '.aac': 'audio/aac',\n\n // 文档\n '.pdf': 'application/pdf',\n '.doc': 'application/msword',\n '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n '.xls': 'application/vnd.ms-excel',\n '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n '.ppt': 'application/vnd.ms-powerpoint',\n '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\n '.txt': 'text/plain',\n '.rtf': 'application/rtf',\n\n // 压缩文件\n '.zip': 'application/zip',\n '.rar': 'application/x-rar-compressed',\n '.7z': 'application/x-7z-compressed',\n '.tar': 'application/x-tar',\n '.gz': 'application/gzip',\n\n // 代码文件\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.xml': 'application/xml',\n '.html': 'text/html',\n '.css': 'text/css',\n '.ts': 'application/typescript',\n\n // 其他\n '.csv': 'text/csv',\n '.md': 'text/markdown',\n};\n\n/**\n * 根据文件名获取 MIME 类型\n *\n * @param filename 文件名\n * @returns MIME 类型\n *\n * @example\n * ```typescript\n * getMimeType('photo.jpg') // 'image/jpeg'\n * getMimeType('video.mp4') // 'video/mp4'\n * getMimeType('unknown.xyz') // 'application/octet-stream'\n * ```\n */\nexport function getMimeType(filename: string): string {\n const ext = path.extname(filename).toLowerCase();\n return MIME_TYPES[ext] || 'application/octet-stream';\n}\n\n/**\n * 根据 MIME 类型获取文件扩展名\n *\n * @param mimeType MIME 类型\n * @returns 文件扩展名(包含点号)\n *\n * @example\n * ```typescript\n * getExtensionFromMimeType('image/jpeg') // '.jpg'\n * getExtensionFromMimeType('video/mp4') // '.mp4'\n * ```\n */\nexport function getExtensionFromMimeType(mimeType: string): string | null {\n for (const [ext, mime] of Object.entries(MIME_TYPES)) {\n if (mime === mimeType) {\n return ext;\n }\n }\n return null;\n}\n\n/**\n * 检查是否为图片类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为图片\n */\nexport function isImageType(mimeType: string): boolean {\n return mimeType.startsWith('image/');\n}\n\n/**\n * 检查是否为视频类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为视频\n */\nexport function isVideoType(mimeType: string): boolean {\n return mimeType.startsWith('video/');\n}\n\n/**\n * 检查是否为音频类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为音频\n */\nexport function isAudioType(mimeType: string): boolean {\n return mimeType.startsWith('audio/');\n}\n\n/**\n * 检查是否为文档类型\n *\n * @param mimeType MIME 类型\n * @returns 是否为文档\n */\nexport function isDocumentType(mimeType: string): boolean {\n const documentTypes = [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument',\n 'text/plain',\n 'application/rtf',\n ];\n return documentTypes.some(type => mimeType.includes(type));\n}\n\n/**\n * 验证 MIME 类型是否在允许列表中\n *\n * @param mimeType MIME 类型\n * @param allowedTypes 允许的类型列表(支持通配符)\n * @returns 是否允许\n *\n * @example\n * ```typescript\n * isAllowedMimeType('image/jpeg', ['image/*']) // true\n * isAllowedMimeType('video/mp4', ['image/*']) // false\n * isAllowedMimeType('image/png', ['image/jpeg']) // false\n * ```\n */\nexport function isAllowedMimeType(\n mimeType: string,\n allowedTypes: string[]\n): boolean {\n return allowedTypes.some(allowed => {\n if (allowed === '*/*') {\n return true;\n }\n if (allowed.endsWith('/*')) {\n const prefix = allowed.slice(0, -2);\n return mimeType.startsWith(prefix + '/');\n }\n return mimeType === allowed;\n });\n}\n\n","// @ts-nocheck\n/**\n * 通用文件服务核心实现\n *\n * 提供统一的文件上传、下载、管理接口\n */\n\nimport { EventEmitter } from 'events';\nimport { v4 as uuidv4 } from 'uuid';\nimport { createHash } from 'crypto';\nimport * as path from 'path';\nimport { createLogger } from '../../logger';\nimport { getMimeType } from './utils/mime';\n\nconst logger = createLogger('UniversalFileService');\n\nimport type {\n StorageType,\n CDNType,\n ProcessorType,\n FileMetadata,\n UploadFileInfo,\n UploadProgress,\n FileQueryOptions,\n PaginatedResult,\n BatchOperationResult,\n FileEvent,\n FileEventListener,\n} from '../types';\n\n// Backend specific types\nimport type {\n UniversalFileServiceConfig,\n IStorageProvider,\n ICDNProvider,\n IFileProcessor,\n} from './types';\n\nimport {\n FileUploadError,\n FileProcessingError,\n StorageProviderError,\n} from '../types';\n\n/**\n * 通用文件服务类\n */\nexport class UniversalFileService extends EventEmitter {\n private config: UniversalFileServiceConfig;\n private storageProviders = new Map<StorageType, IStorageProvider>();\n private cdnProviders = new Map<CDNType, ICDNProvider>();\n private fileProcessors = new Map<ProcessorType, IFileProcessor>();\n private uploadProgressMap = new Map<string, UploadProgress>();\n private metadataCache = new Map<string, { data: FileMetadata; expires: number }>();\n private urlCache = new Map<string, { url: string; expires: number }>();\n private processingQueue: Array<{\n fileId: string;\n processor: IFileProcessor;\n inputPath: string;\n outputPath: string;\n options: any;\n }> = [];\n private isProcessingQueueRunning = false;\n\n constructor(config: UniversalFileServiceConfig) {\n super();\n this.config = config;\n\n // 如果启用了持久化,设置自动监听器\n if (this.config.persistence?.enabled && this.config.persistence.repository) {\n this.setupPersistenceListeners();\n }\n }\n\n // ============= 持久化设置 =============\n\n /**\n * 设置数据库持久化监听器\n *\n * 当文件上传完成或删除时,自动触发数据库操作\n */\n private setupPersistenceListeners(): void {\n const { repository, autoPersist = true } = this.config.persistence!;\n\n if (!autoPersist) {\n logger.info('⚙️ [UniversalFileService] 自动持久化已禁用');\n return;\n }\n\n logger.info('✅ [UniversalFileService] 已启用数据库持久化,自动监听文件事件');\n\n // 监听文件上传完成事件\n this.on('upload:complete', async (fileId: string, data: any) => {\n try {\n const metadata = data.metadata || data;\n await repository.save(metadata);\n logger.info(`💾 [Persistence] 文件元数据已自动保存: ${fileId}`);\n } catch (error) {\n logger.error(`❌ [Persistence] 保存失败: ${fileId}`, error);\n // 不抛出错误,避免影响上传流程\n }\n });\n\n // 监听文件删除事件\n this.on('file:deleted', async (fileId: string) => {\n try {\n await repository.delete(fileId);\n logger.info(`🗑️ [Persistence] 文件元数据已自动删除: ${fileId}`);\n } catch (error) {\n logger.error(`❌ [Persistence] 删除失败: ${fileId}`, error);\n }\n });\n\n // 监听批量删除事件\n this.on('files:batch-deleted', async (fileIds: string[]) => {\n try {\n await repository.batchDelete(fileIds);\n logger.info(`🗑️ [Persistence] 批量删除元数据: ${fileIds.length} 个文件`);\n } catch (error) {\n logger.error(`❌ [Persistence] 批量删除失败`, error);\n }\n });\n }\n\n // ============= 初始化方法 =============\n\n /**\n * 初始化文件服务\n */\n async initialize(): Promise<void> {\n logger.info('🚀 [UniversalFileService] 开始初始化文件服务...');\n\n try {\n // 初始化存储提供者\n await this.initializeStorageProviders();\n\n // 初始化CDN提供者\n await this.initializeCDNProviders();\n\n // 初始化文件处理器\n await this.initializeFileProcessors();\n\n logger.info('✅ [UniversalFileService] 文件服务初始化完成');\n } catch (error) {\n console.error('❌ [UniversalFileService] 文件服务初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 重新初始化存储提供者(支持配置热更新)\n */\n async reinitializeStorageProviders(): Promise<void> {\n logger.info('🔄 [UniversalFileService] 重新初始化存储提供者...');\n\n try {\n // 重新初始化OSS提供者\n const ossConfig = this.config.storageProviders['aliyun-oss'];\n if (ossConfig && ossConfig.enabled) {\n const ossProvider = this.storageProviders.get('aliyun-oss');\n if (ossProvider && 'reinitialize' in ossProvider) {\n logger.info('🔄 [UniversalFileService] 重新初始化阿里云OSS提供者...');\n await (ossProvider as any).reinitialize(ossConfig);\n }\n }\n\n logger.info('✅ [UniversalFileService] 存储提供者重新初始化完成');\n } catch (error) {\n console.error('❌ [UniversalFileService] 存储提供者重新初始化失败:', error);\n throw error;\n }\n }\n\n /**\n * 注册存储提供者\n */\n registerStorageProvider(provider: IStorageProvider): void {\n this.storageProviders.set(provider.type, provider);\n logger.info(`📦 [UniversalFileService] 注册存储提供者: ${provider.type}`);\n }\n\n /**\n * 注册CDN提供者\n */\n registerCDNProvider(provider: ICDNProvider): void {\n this.cdnProviders.set(provider.type, provider);\n logger.info(`🌐 [UniversalFileService] 注册CDN提供者: ${provider.type}`);\n }\n\n /**\n * 注册文件处理器\n */\n registerFileProcessor(processor: IFileProcessor): void {\n this.fileProcessors.set(processor.type, processor);\n logger.info(`⚙️ [UniversalFileService] 注册文件处理器: ${processor.type}`);\n }\n\n // ============= 核心文件操作方法 =============\n\n /**\n * 上传文件\n */\n async uploadFile(\n fileInfo: UploadFileInfo,\n storageType?: StorageType,\n onProgress?: (progress: UploadProgress) => void\n ): Promise<FileMetadata> {\n const fileId = uuidv4();\n const startTime = Date.now();\n\n logger.info(`📤 [UniversalFileService] 开始上传文件: ${fileInfo.file.name}, ID: ${fileId}`);\n\n try {\n // 验证文件\n await this.validateFile(fileInfo.file);\n\n // 初始化上传进度\n const progress: UploadProgress = {\n fileId,\n status: 'pending',\n progress: 0,\n uploadedBytes: 0,\n totalBytes: fileInfo.file.size,\n speed: 0,\n remainingTime: 0,\n };\n\n this.uploadProgressMap.set(fileId, progress);\n this.emitFileEvent('upload:start', fileId, { fileName: fileInfo.file.name });\n\n // 生成文件元数据\n const metadata = await this.generateFileMetadata(fileId, fileInfo);\n\n // 选择存储提供者\n const selectedStorageType = storageType || this.config.defaultStorage;\n let storageProvider = this.storageProviders.get(selectedStorageType);\n\n // 如果指定的存储提供者不可用,优先尝试OSS\n if (!storageProvider) {\n logger.info(\n `⚠️ [UniversalFileService] 存储提供者 ${selectedStorageType} 不可用,尝试使用OSS`\n );\n storageProvider = this.storageProviders.get('aliyun-oss');\n\n // 如果OSS也不可用,回退到本地存储\n if (!storageProvider) {\n logger.info(`⚠️ [UniversalFileService] OSS不可用,回退到本地存储`);\n storageProvider = this.storageProviders.get('local');\n }\n }\n\n if (!storageProvider) {\n throw new StorageProviderError(`没有可用的存储提供者`);\n }\n\n // 生成存储路径\n const storagePath = this.generateStoragePath(metadata);\n\n // 更新上传状态\n progress.status = 'uploading';\n progress.progress = 10;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n this.emitFileEvent('upload:progress', fileId, { progress: progress.progress });\n\n // 执行上传\n const uploadResult = await storageProvider.upload(fileInfo, storagePath);\n\n if (!uploadResult.success) {\n throw new FileUploadError(`上传失败: ${uploadResult.error}`);\n }\n\n // 更新元数据\n metadata.storagePath = uploadResult.path || storagePath;\n metadata.storageProvider = selectedStorageType;\n\n // 生成CDN URL(如果启用)\n if (this.config.defaultCDN !== 'none') {\n const cdnProvider = this.cdnProviders.get(this.config.defaultCDN);\n if (cdnProvider && uploadResult.url) {\n metadata.cdnUrl = await cdnProvider.generateUrl(uploadResult.url);\n }\n }\n\n // 更新上传进度\n progress.status = fileInfo.needsProcessing ? 'processing' : 'completed';\n progress.progress = fileInfo.needsProcessing ? 70 : 100;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n\n // 如果需要处理,添加到处理队列\n if (fileInfo.needsProcessing && fileInfo.processingOptions) {\n await this.queueFileProcessing(metadata, fileInfo.processingOptions);\n }\n\n // 缓存元数据\n this.cacheMetadata(metadata);\n\n // 保存到数据库通过事件触发(如果启用了持久化)\n // persistence.repository 会监听 'upload:complete' 事件自动保存\n\n // 完成上传\n progress.status = 'completed';\n progress.progress = 100;\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n\n const uploadTime = Date.now() - startTime;\n logger.info(`✅ [UniversalFileService] 文件上传完成: ${fileId}, 耗时: ${uploadTime}ms`);\n\n this.emitFileEvent('upload:complete', fileId, {\n fileName: fileInfo.file.name,\n size: fileInfo.file.size,\n uploadTime,\n });\n\n return metadata;\n } catch (error) {\n console.error(`❌ [UniversalFileService] 文件上传失败: ${fileId}:`, error);\n\n // 更新上传状态为失败\n const progress = this.uploadProgressMap.get(fileId);\n if (progress) {\n progress.status = 'failed';\n progress.error = error instanceof Error ? error.message : '上传失败';\n this.uploadProgressMap.set(fileId, progress);\n onProgress?.(progress);\n }\n\n this.emitFileEvent(\n 'upload:error',\n fileId,\n undefined,\n error instanceof Error ? error.message : '上传失败'\n );\n throw error;\n } finally {\n // 清理上传进度(可选,或设置过期时间)\n setTimeout(\n () => {\n this.uploadProgressMap.delete(fileId);\n },\n 5 * 60 * 1000\n ); // 5分钟后清理\n }\n }\n\n\n /**\n * 获取上传进度\n */\n getUploadProgress(fileId: string): UploadProgress | undefined {\n return this.uploadProgressMap.get(fileId);\n }\n\n // ============= 事件处理方法 =============\n\n /**\n * 监听文件事件\n */\n onFileEvent(eventType: string, listener: FileEventListener): void {\n this.on(eventType, listener);\n }\n\n /**\n * 移除文件事件监听器\n */\n offFileEvent(eventType: string, listener: FileEventListener): void {\n this.off(eventType, listener);\n }\n\n // ============= 私有方法 =============\n\n private async initializeStorageProviders(): Promise<void> {\n logger.info('📦 [UniversalFileService] 开始初始化存储提供者...');\n\n // 如果还没有注册任何存储提供者,先注册默认的\n if (this.storageProviders.size === 0) {\n await this.registerDefaultStorageProviders();\n }\n\n for (const [type, config] of Object.entries(this.config.storageProviders)) {\n if (config.enabled) {\n const provider = this.storageProviders.get(type as StorageType);\n if (provider) {\n try {\n await provider.initialize(config);\n logger.info(`✅ [UniversalFileService] 存储提供者初始化完成: ${type}`);\n } catch (error) {\n console.warn(`⚠️ [UniversalFileService] 存储提供者初始化失败: ${type}:`, error);\n // 如果默认存储提供者初始化失败,切换到本地存储\n // if (type === this.config.defaultStorage) {\n // console.warn(`⚠️ [UniversalFileService] 默认存储提供者 ${type} 初始化失败,切换到本地存储`);\n // this.config.defaultStorage = 'local';\n // }\n }\n } else {\n console.warn(`⚠️ [UniversalFileService] 存储提供者未注册: ${type}`);\n }\n }\n }\n }\n\n private async registerDefaultStorageProviders(): Promise<void> {\n logger.info('📦 [UniversalFileService] 注册默认存储提供者...');\n\n // 优先注册OSS提供者\n const ossConfig = this.config.storageProviders['aliyun-oss'];\n if (ossConfig && ossConfig.enabled) {\n try {\n const { AliyunOSSProvider } = await import('./providers/AliyunOSSProvider');\n const ossProvider = new AliyunOSSProvider();\n this.registerStorageProvider(ossProvider);\n logger.info('✅ [UniversalFileService] 阿里云OSS提供者注册成功');\n } catch (error) {\n console.warn('⚠️ [UniversalFileService] 阿里云OSS提供者注册失败:', error);\n }\n }\n\n // 注册本地存储提供者作为备用\n const localConfig = this.config.storageProviders['local'];\n if (localConfig && localConfig.enabled) {\n try {\n const { LocalStorageProvider } = await import('./providers/LocalStorageProvider');\n const localProvider = new LocalStorageProvider();\n this.registerStorageProvider(localProvider);\n logger.info('✅ [UniversalFileService] 本地存储提供者注册成功');\n } catch (error) {\n console.warn('⚠️ [UniversalFileService] 本地存储提供者注册失败:', error);\n }\n }\n\n // 确保至少有一个可用的存储提供者\n if (this.storageProviders.size === 0) {\n console.warn('⚠️ [UniversalFileService] 没有可用的存储提供者,尝试注册本地存储作为备用');\n try {\n const { LocalStorageProvider } = await import('./providers/LocalStorageProvider');\n const localProvider = new LocalStorageProvider();\n this.registerStorageProvider(localProvider);\n logger.info('✅ [UniversalFileService] 本地存储提供者注册成功(备用)');\n } catch (error) {\n console.error('❌ [UniversalFileService] 无法注册任何存储提供者:', error);\n throw new Error('无法初始化存储提供者');\n }\n }\n }\n\n private async initializeCDNProviders(): Promise<void> {\n for (const [type, config] of Object.entries(this.config.cdnProviders)) {\n if (config.enabled) {\n const provider = this.cdnProviders.get(type as CDNType);\n if (provider) {\n await provider.initialize(config);\n logger.info(`✅ [UniversalFileService] CDN提供者初始化完成: ${type}`);\n }\n }\n }\n }\n\n private async initializeFileProcessors(): Promise<void> {\n for (const processor of Array.from(this.fileProcessors.values())) {\n await processor.initialize();\n logger.info(`✅ [UniversalFileService] 文件处理器初始化完成: ${processor.type}`);\n }\n }\n\n private async validateFile(file: File): Promise<void> {\n // 检查文件大小\n if (file.size > this.config.maxFileSize) {\n throw new FileUploadError(`文件大小超过限制: ${file.size} > ${this.config.maxFileSize}`);\n }\n\n // 检查文件类型\n const mimeType = file.type || getMimeType(file.name);\n\n if (\n this.config.allowedMimeTypes.length > 0 &&\n !this.config.allowedMimeTypes.includes(mimeType)\n ) {\n throw new FileUploadError(`不支持的文件类型: ${mimeType}`);\n }\n }\n\n private async generateFileMetadata(\n fileId: string,\n fileInfo: UploadFileInfo\n ): Promise<FileMetadata> {\n const now = new Date();\n const mimeType = fileInfo.file.type || getMimeType(fileInfo.file.name);\n const extension = path.extname(fileInfo.file.name).toLowerCase();\n\n // 生成文件哈希(用于去重检测)\n const hash = await this.generateFileHash(fileInfo.file);\n\n return {\n id: fileId,\n originalName: fileInfo.file.name,\n storageName: `${fileId}${extension}`,\n size: fileInfo.file.size,\n mimeType,\n extension,\n hash,\n uploadTime: now,\n permission: fileInfo.permission || 'public',\n uploaderId: fileInfo.metadata?.uploadedBy || 'system',\n moduleId: fileInfo.moduleId,\n businessId: fileInfo.businessId,\n storageProvider: this.config.defaultStorage,\n storagePath: '',\n accessCount: 0,\n metadata: fileInfo.metadata || {},\n };\n }\n\n private generateStoragePath(metadata: FileMetadata): string {\n const date = new Date();\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return `${metadata.moduleId}/${year}/${month}/${day}/${metadata.storageName}`;\n }\n\n private async generateFileHash(file: File): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hash = createHash('sha256');\n hash.update(Buffer.from(buffer));\n return hash.digest('hex');\n }\n\n private async queueFileProcessing(metadata: FileMetadata, options: any): Promise<void> {\n if (!this.config.processors?.length || 0 > 0) {\n return;\n }\n\n const processor = this.fileProcessors.get(options.type);\n if (!processor) {\n console.warn(`⚠️ [UniversalFileService] 文件处理器不存在: ${options.type}`);\n return;\n }\n\n if (this.processingQueue.length >= 1000) {\n throw new FileProcessingError('处理队列已满');\n }\n\n this.processingQueue.push({\n fileId: metadata.id,\n processor,\n inputPath: metadata.storagePath,\n outputPath: this.generateProcessedPath(metadata, options),\n options,\n });\n\n // 启动处理队列\n if (!this.isProcessingQueueRunning) {\n this.processFileQueue();\n }\n }\n\n private generateProcessedPath(metadata: FileMetadata, options: any): string {\n const basePath = metadata.storagePath;\n const extension = path.extname(basePath);\n const basename = basePath.replace(extension, '');\n\n return `${basename}_processed${extension}`;\n }\n\n private async processFileQueue(): Promise<void> {\n if (this.isProcessingQueueRunning || this.processingQueue.length === 0) {\n return;\n }\n\n this.isProcessingQueueRunning = true;\n\n while (this.processingQueue.length > 0) {\n const task = this.processingQueue.shift();\n if (!task) break;\n\n try {\n this.emitFileEvent('processing:start', task.fileId);\n\n const result = await task.processor.process(task.inputPath, task.outputPath, task.options);\n\n if (result.success) {\n this.emitFileEvent('processing:complete', task.fileId, result);\n } else {\n this.emitFileEvent('processing:error', task.fileId, undefined, result.error);\n }\n } catch (error) {\n console.error(`❌ [UniversalFileService] 文件处理失败: ${task.fileId}:`, error);\n this.emitFileEvent(\n 'processing:error',\n task.fileId,\n undefined,\n error instanceof Error ? error.message : '处理失败'\n );\n }\n }\n\n this.isProcessingQueueRunning = false;\n }\n\n private cacheMetadata(metadata: FileMetadata): void {\n const expires = Date.now() + (this.config.cache?.metadataTTL || 3600) * 1000;\n this.metadataCache.set(metadata.id, { data: metadata, expires });\n }\n\n private _clearMetadataCache2(fileId: string): void {\n this.metadataCache.delete(fileId);\n }\n\n private emitFileEvent(type: string, fileId: string, data?: any, error?: string): void {\n const event: FileEvent = {\n type: type as any,\n fileId,\n timestamp: new Date(),\n data,\n error,\n };\n\n this.emit(type, event);\n this.emit('*', event); // 通用事件监听\n }\n}\n","/**\n * 通用文件服务缓存管理器\n * 支持多层缓存策略:内存缓存 + Redis缓存\n */\n\nimport { LRUCache } from 'lru-cache';\nimport { createLogger } from '../../../logger';\n\nconst logger = createLogger('CacheManager');\n\n/**\n * 缓存项接口\n */\ninterface CacheItem<T = any> {\n /** 缓存数据 */\n data: T;\n /** 创建时间 */\n createdAt: number;\n /** 过期时间 */\n expiresAt: number;\n /** 访问次数 */\n accessCount: number;\n /** 最后访问时间 */\n lastAccessAt: number;\n}\n\n/**\n * 缓存统计信息\n */\ninterface CacheStats {\n /** 总请求次数 */\n totalRequests: number;\n /** 命中次数 */\n hits: number;\n /** 未命中次数 */\n misses: number;\n /** 命中率 */\n hitRate: number;\n /** 内存缓存大小 */\n memorySize: number;\n /** Redis缓存状态 */\n redisConnected: boolean;\n}\n\n/**\n * 缓存配置选项\n */\ninterface CacheOptions {\n /** 默认过期时间(秒) */\n defaultTTL?: number;\n /** 内存缓存最大条目数 */\n maxMemoryItems?: number;\n /** 是否启用Redis缓存 */\n enableRedis?: boolean;\n /** Redis连接配置 */\n redisConfig?: {\n host: string;\n port: number;\n password?: string;\n db?: number;\n };\n /** 缓存键前缀 */\n keyPrefix?: string;\n}\n\n/**\n * 缓存管理器\n */\nexport class CacheManager {\n private memoryCache: LRUCache<string, CacheItem>;\n private redisClient: any = null;\n private stats: CacheStats;\n private options: Required<CacheOptions>;\n\n constructor(options: CacheOptions = {}) {\n this.options = {\n defaultTTL: options.defaultTTL || 300, // 5分钟\n maxMemoryItems: options.maxMemoryItems || 1000,\n enableRedis: options.enableRedis || false,\n redisConfig: options.redisConfig || {\n host: 'localhost',\n port: 6379,\n db: 0,\n },\n keyPrefix: options.keyPrefix || 'universal-file:',\n };\n\n // 初始化内存缓存\n this.memoryCache = new LRUCache({\n max: this.options.maxMemoryItems,\n ttl: this.options.defaultTTL * 1000, // LRU缓存使用毫秒\n updateAgeOnGet: true,\n allowStale: false,\n });\n\n // 初始化统计信息\n this.stats = {\n totalRequests: 0,\n hits: 0,\n misses: 0,\n hitRate: 0,\n memorySize: 0,\n redisConnected: false,\n };\n\n // 初始化Redis连接(如果启用)\n if (this.options.enableRedis) {\n this.initRedis();\n }\n }\n\n /**\n * 初始化Redis连接\n */\n private async initRedis() {\n try {\n // 这里可以集成实际的Redis客户端,如ioredis\n // const Redis = require('ioredis');\n // this.redisClient = new Redis(this.options.redisConfig);\n\n logger.info('Redis缓存已禁用 - 请安装并配置Redis客户端');\n this.stats.redisConnected = false;\n } catch (error) {\n console.error('Redis连接失败:', error);\n this.stats.redisConnected = false;\n }\n }\n\n /**\n * 生成缓存键\n */\n private generateKey(key: string): string {\n return `${this.options.keyPrefix}${key}`;\n }\n\n /**\n * 获取缓存数据\n */\n async get<T = any>(key: string): Promise<T | null> {\n const cacheKey = this.generateKey(key);\n this.stats.totalRequests++;\n\n try {\n // 首先尝试从内存缓存获取\n const memoryItem = this.memoryCache.get(cacheKey);\n if (memoryItem && memoryItem.expiresAt > Date.now()) {\n memoryItem.accessCount++;\n memoryItem.lastAccessAt = Date.now();\n this.stats.hits++;\n this.updateHitRate();\n return memoryItem.data as T;\n }\n\n // 如果内存缓存未命中,尝试从Redis获取\n if (this.redisClient && this.stats.redisConnected) {\n const redisData = await this.redisClient.get(cacheKey);\n if (redisData) {\n const parsedData = JSON.parse(redisData);\n\n // 将数据放回内存缓存\n const cacheItem: CacheItem<T> = {\n data: parsedData.data,\n createdAt: parsedData.createdAt,\n expiresAt: parsedData.expiresAt,\n accessCount: parsedData.accessCount + 1,\n lastAccessAt: Date.now(),\n };\n\n this.memoryCache.set(cacheKey, cacheItem);\n this.stats.hits++;\n this.updateHitRate();\n return parsedData.data as T;\n }\n }\n\n // 缓存未命中\n this.stats.misses++;\n this.updateHitRate();\n return null;\n } catch (error) {\n console.error('缓存获取失败:', error);\n this.stats.misses++;\n this.updateHitRate();\n return null;\n }\n }\n\n /**\n * 设置缓存数据\n */\n async set<T = any>(key: string, data: T, ttl?: number): Promise<void> {\n const cacheKey = this.generateKey(key);\n const expireTime = ttl || this.options.defaultTTL;\n const now = Date.now();\n\n const cacheItem: CacheItem<T> = {\n data,\n createdAt: now,\n expiresAt: now + expireTime * 1000,\n accessCount: 0,\n lastAccessAt: now,\n };\n\n try {\n // 设置到内存缓存\n this.memoryCache.set(cacheKey, cacheItem);\n\n // 如果启用Redis,也设置到Redis\n if (this.redisClient && this.stats.redisConnected) {\n await this.redisClient.setex(cacheKey, expireTime, JSON.stringify(cacheItem));\n }\n\n this.updateMemorySize();\n } catch (error) {\n console.error('缓存设置失败:', error);\n }\n }\n\n /**\n * 删除缓存数据\n */\n async delete(key: string): Promise<void> {\n const cacheKey = this.generateKey(key);\n\n try {\n // 从内存缓存删除\n this.memoryCache.delete(cacheKey);\n\n // 从Redis删除\n if (this.redisClient && this.stats.redisConnected) {\n await this.redisClient.del(cacheKey);\n }\n\n this.updateMemorySize();\n } catch (error) {\n console.error('缓存删除失败:', error);\n }\n }\n\n /**\n * 批量删除缓存(支持模式匹配)\n */\n async deletePattern(pattern: string): Promise<void> {\n const cachePattern = this.generateKey(pattern);\n\n try {\n // 清理内存缓存中匹配的项\n const keys = Array.from(this.memoryCache.keys());\n for (const key of keys) {\n if (this.matchPattern(key, cachePattern)) {\n this.memoryCache.delete(key);\n }\n }\n\n // 清理Redis中匹配的项\n if (this.redisClient && this.stats.redisConnected) {\n const redisKeys = await this.redisClient.keys(cachePattern);\n if (redisKeys.length > 0) {\n await this.redisClient.del(...redisKeys);\n }\n }\n\n this.updateMemorySize();\n } catch (error) {\n console.error('批量缓存删除失败:', error);\n }\n }\n\n /**\n * 清空所有缓存\n */\n async clear(): Promise<void> {\n try {\n // 清空内存缓存\n this.memoryCache.clear();\n\n // 清空Redis缓存(仅删除带前缀的键)\n if (this.redisClient && this.stats.redisConnected) {\n const keys = await this.redisClient.keys(`${this.options.keyPrefix}*`);\n if (keys.length > 0) {\n await this.redisClient.del(...keys);\n }\n }\n\n // 重置统计信息\n this.stats.hits = 0;\n this.stats.misses = 0;\n this.stats.totalRequests = 0;\n this.stats.hitRate = 0;\n this.updateMemorySize();\n } catch (error) {\n console.error('清空缓存失败:', error);\n }\n }\n\n /**\n * 获取缓存统计信息\n */\n getStats(): CacheStats {\n this.updateMemorySize();\n return { ...this.stats };\n }\n\n /**\n * 获取缓存项详情(用于调试)\n */\n getCacheItem(key: string): CacheItem | null {\n const cacheKey = this.generateKey(key);\n return this.memoryCache.get(cacheKey) || null;\n }\n\n /**\n * 预热缓存\n */\n async warmup<T>(items: Array<{ key: string; data: T; ttl?: number }>): Promise<void> {\n logger.info(`开始预热缓存,共 ${items.length} 项...`);\n\n const promises = items.map((item) => this.set(item.key, item.data, item.ttl));\n\n try {\n await Promise.all(promises);\n logger.info('缓存预热完成');\n } catch (error) {\n console.error('缓存预热失败:', error);\n }\n }\n\n /**\n * 更新命中率\n */\n private updateHitRate(): void {\n this.stats.hitRate =\n this.stats.totalRequests > 0 ? (this.stats.hits / this.stats.totalRequests) * 100 : 0;\n }\n\n /**\n * 更新内存使用量\n */\n private updateMemorySize(): void {\n this.stats.memorySize = this.memoryCache.size;\n }\n\n /**\n * 模式匹配函数\n */\n private matchPattern(key: string, pattern: string): boolean {\n // 简单的通配符匹配,* 匹配任意字符\n const regexPattern = pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.');\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(key);\n }\n\n /**\n * 获取或设置缓存(如果不存在则调用生成函数)\n */\n async getOrSet<T>(key: string, generator: () => Promise<T>, ttl?: number): Promise<T> {\n // 尝试获取缓存\n const cachedData = await this.get<T>(key);\n if (cachedData !== null) {\n return cachedData;\n }\n\n // 缓存不存在,调用生成函数\n try {\n const data = await generator();\n await this.set(key, data, ttl);\n return data;\n } catch (error) {\n console.error('缓存生成失败:', error);\n throw error;\n }\n }\n\n /**\n * 关闭缓存管理器\n */\n async close(): Promise<void> {\n try {\n // 清理内存缓存\n this.memoryCache.clear();\n\n // 关闭Redis连接\n if (this.redisClient) {\n await this.redisClient.quit();\n }\n } catch (error) {\n console.error('关闭缓存管理器失败:', error);\n }\n }\n}\n\n/**\n * 单例缓存管理器实例\n */\nexport const cacheManager = new CacheManager({\n defaultTTL: 300, // 5分钟\n maxMemoryItems: 2000,\n enableRedis: false, // 开发环境暂时禁用Redis\n keyPrefix: 'universal-file:',\n});\n","/**\n * 通用文件服务性能监控器\n * 监控API响应时间、数据库查询性能、缓存命中率等指标\n */\n\n/**\n * 性能指标类型\n */\ninterface PerformanceMetric {\n /** 指标名称 */\n name: string;\n /** 指标值 */\n value: number;\n /** 单位 */\n unit: string;\n /** 时间戳 */\n timestamp: number;\n /** 标签 */\n labels?: Record<string, string>;\n}\n\n/**\n * 性能统计信息\n */\ninterface PerformanceStats {\n /** API响应时间统计 */\n apiResponseTimes: {\n /** 平均响应时间(毫秒) */\n average: number;\n /** 最小响应时间 */\n min: number;\n /** 最大响应时间 */\n max: number;\n /** P95响应时间 */\n p95: number;\n /** P99响应时间 */\n p99: number;\n /** 总请求数 */\n totalRequests: number;\n };\n\n /** 数据库查询性能 */\n databasePerformance: {\n /** 平均查询时间(毫秒) */\n averageQueryTime: number;\n /** 慢查询数量 */\n slowQueries: number;\n /** 总查询数 */\n totalQueries: number;\n /** 查询错误数 */\n queryErrors: number;\n };\n\n /** 文件操作性能 */\n fileOperations: {\n /** 文件上传统计 */\n uploads: {\n /** 总上传数 */\n total: number;\n /** 成功上传数 */\n successful: number;\n /** 失败上传数 */\n failed: number;\n /** 平均上传时间 */\n averageTime: number;\n /** 平均文件大小 */\n averageSize: number;\n };\n\n /** 文件下载统计 */\n downloads: {\n /** 总下载数 */\n total: number;\n /** 成功下载数 */\n successful: number;\n /** 失败下载数 */\n failed: number;\n /** 平均下载时间 */\n averageTime: number;\n };\n };\n\n /** 系统资源使用 */\n systemResources: {\n /** 内存使用量(MB) */\n memoryUsage: number;\n /** CPU使用率(%) */\n cpuUsage: number;\n /** 磁盘使用量(MB) */\n diskUsage: number;\n };\n}\n\n/**\n * 请求跟踪信息\n */\ninterface RequestTrace {\n /** 请求ID */\n requestId: string;\n /** 请求路径 */\n path: string;\n /** HTTP方法 */\n method: string;\n /** 开始时间 */\n startTime: number;\n /** 结束时间 */\n endTime?: number;\n /** 响应时间(毫秒) */\n duration?: number;\n /** 状态码 */\n statusCode?: number;\n /** 错误信息 */\n error?: string;\n /** 用户ID */\n userId?: string;\n /** 文件大小(字节) */\n fileSize?: number;\n}\n\n/**\n * 性能监控器\n */\nexport class PerformanceMonitor {\n private metrics: PerformanceMetric[] = [];\n private requestTraces: Map<string, RequestTrace> = new Map();\n private stats: PerformanceStats;\n private readonly maxMetrics = 10000; // 最大保存指标数量\n private readonly maxTraces = 1000; // 最大保存跟踪数量\n\n constructor() {\n this.stats = this.initializeStats();\n\n // 定期清理过期数据\n setInterval(() => {\n this.cleanupOldData();\n }, 60000); // 每分钟清理一次\n }\n\n /**\n * 初始化统计信息\n */\n private initializeStats(): PerformanceStats {\n return {\n apiResponseTimes: {\n average: 0,\n min: 0,\n max: 0,\n p95: 0,\n p99: 0,\n totalRequests: 0,\n },\n databasePerformance: {\n averageQueryTime: 0,\n slowQueries: 0,\n totalQueries: 0,\n queryErrors: 0,\n },\n fileOperations: {\n uploads: {\n total: 0,\n successful: 0,\n failed: 0,\n averageTime: 0,\n averageSize: 0,\n },\n downloads: {\n total: 0,\n successful: 0,\n failed: 0,\n averageTime: 0,\n },\n },\n systemResources: {\n memoryUsage: 0,\n cpuUsage: 0,\n diskUsage: 0,\n },\n };\n }\n\n /**\n * 开始请求跟踪\n */\n startRequest(requestId: string, path: string, method: string, userId?: string): void {\n const trace: RequestTrace = {\n requestId,\n path,\n method,\n startTime: Date.now(),\n userId,\n };\n\n this.requestTraces.set(requestId, trace);\n }\n\n /**\n * 结束请求跟踪\n */\n endRequest(requestId: string, statusCode: number, error?: string, fileSize?: number): void {\n const trace = this.requestTraces.get(requestId);\n if (!trace) return;\n\n const endTime = Date.now();\n const duration = endTime - trace.startTime;\n\n trace.endTime = endTime;\n trace.duration = duration;\n trace.statusCode = statusCode;\n trace.error = error;\n trace.fileSize = fileSize;\n\n // 记录API响应时间指标\n this.recordMetric('api_response_time', duration, 'ms', {\n path: trace.path,\n method: trace.method,\n status: statusCode.toString(),\n });\n\n // 更新统计信息\n this.updateApiStats(duration);\n\n // 如果是文件操作,更新文件操作统计\n if (trace.path.includes('upload')) {\n this.updateUploadStats(statusCode < 400, duration, fileSize);\n } else if (trace.path.includes('download')) {\n this.updateDownloadStats(statusCode < 400, duration);\n }\n\n // 如果跟踪数量过多,删除最旧的\n if (this.requestTraces.size > this.maxTraces) {\n const oldestKey = this.requestTraces.keys().next().value;\n if (oldestKey) {\n this.requestTraces.delete(oldestKey);\n }\n }\n }\n\n /**\n * 记录数据库查询性能\n */\n recordDatabaseQuery(queryTime: number, isError: boolean = false): void {\n this.recordMetric('db_query_time', queryTime, 'ms');\n\n this.stats.databasePerformance.totalQueries++;\n\n if (isError) {\n this.stats.databasePerformance.queryErrors++;\n }\n\n // 更新平均查询时间\n const total = this.stats.databasePerformance.totalQueries;\n const currentAvg = this.stats.databasePerformance.averageQueryTime;\n this.stats.databasePerformance.averageQueryTime =\n (currentAvg * (total - 1) + queryTime) / total;\n\n // 记录慢查询(超过1秒)\n if (queryTime > 1000) {\n this.stats.databasePerformance.slowQueries++;\n this.recordMetric('slow_query', 1, 'count');\n }\n }\n\n /**\n * 记录系统资源使用情况\n */\n recordSystemResources(): void {\n try {\n // 获取内存使用情况\n const memoryUsage = process.memoryUsage();\n const memoryUsedMB = memoryUsage.heapUsed / 1024 / 1024;\n\n this.stats.systemResources.memoryUsage = memoryUsedMB;\n this.recordMetric('memory_usage', memoryUsedMB, 'MB');\n\n // 记录其他系统指标(简化版本)\n this.recordMetric('heap_total', memoryUsage.heapTotal / 1024 / 1024, 'MB');\n this.recordMetric('heap_used', memoryUsage.heapUsed / 1024 / 1024, 'MB');\n this.recordMetric('external', memoryUsage.external / 1024 / 1024, 'MB');\n } catch (error) {\n console.error('记录系统资源失败:', error);\n }\n }\n\n /**\n * 记录自定义指标\n */\n recordMetric(name: string, value: number, unit: string, labels?: Record<string, string>): void {\n const metric: PerformanceMetric = {\n name,\n value,\n unit,\n timestamp: Date.now(),\n labels,\n };\n\n this.metrics.push(metric);\n\n // 如果指标数量过多,删除最旧的\n if (this.metrics.length > this.maxMetrics) {\n this.metrics.shift();\n }\n }\n\n /**\n * 获取性能统计信息\n */\n getStats(): PerformanceStats {\n // 更新系统资源信息\n this.recordSystemResources();\n\n return { ...this.stats };\n }\n\n /**\n * 获取指定时间范围内的指标\n */\n getMetrics(name?: string, startTime?: number, endTime?: number): PerformanceMetric[] {\n let filteredMetrics = this.metrics;\n\n if (name) {\n filteredMetrics = filteredMetrics.filter((m) => m.name === name);\n }\n\n if (startTime) {\n filteredMetrics = filteredMetrics.filter((m) => m.timestamp >= startTime);\n }\n\n if (endTime) {\n filteredMetrics = filteredMetrics.filter((m) => m.timestamp <= endTime);\n }\n\n return filteredMetrics;\n }\n\n /**\n * 获取请求跟踪信息\n */\n getRequestTraces(limit: number = 100): RequestTrace[] {\n const traces = Array.from(this.requestTraces.values());\n return traces.sort((a, b) => b.startTime - a.startTime).slice(0, limit);\n }\n\n /**\n * 获取慢请求列表\n */\n getSlowRequests(threshold: number = 1000): RequestTrace[] {\n return this.getRequestTraces()\n .filter((trace) => trace.duration && trace.duration > threshold)\n .sort((a, b) => (b.duration || 0) - (a.duration || 0));\n }\n\n /**\n * 获取错误请求列表\n */\n getErrorRequests(): RequestTrace[] {\n return this.getRequestTraces().filter((trace) => trace.statusCode && trace.statusCode >= 400);\n }\n\n /**\n * 生成性能报告\n */\n generateReport(): {\n summary: any;\n topSlowRequests: RequestTrace[];\n recentErrors: RequestTrace[];\n systemHealth: any;\n } {\n const stats = this.getStats();\n const slowRequests = this.getSlowRequests(500); // 500ms以上的请求\n const errorRequests = this.getErrorRequests();\n\n return {\n summary: {\n totalRequests: stats.apiResponseTimes.totalRequests,\n averageResponseTime: stats.apiResponseTimes.average,\n errorRate: (errorRequests.length / Math.max(stats.apiResponseTimes.totalRequests, 1)) * 100,\n cacheHitRate: 0, // 需要从缓存管理器获取\n slowQueryCount: stats.databasePerformance.slowQueries,\n },\n topSlowRequests: slowRequests.slice(0, 10),\n recentErrors: errorRequests.slice(0, 10),\n systemHealth: {\n memoryUsage: stats.systemResources.memoryUsage,\n queryPerformance: stats.databasePerformance.averageQueryTime,\n uptime: process.uptime(),\n },\n };\n }\n\n /**\n * 更新API统计信息\n */\n private updateApiStats(duration: number): void {\n const stats = this.stats.apiResponseTimes;\n stats.totalRequests++;\n\n // 更新平均响应时间\n stats.average = (stats.average * (stats.totalRequests - 1) + duration) / stats.totalRequests;\n\n // 更新最小/最大值\n if (stats.totalRequests === 1 || duration < stats.min) {\n stats.min = duration;\n }\n if (stats.totalRequests === 1 || duration > stats.max) {\n stats.max = duration;\n }\n\n // 计算百分位数(简化版本)\n const recentDurations = this.getMetrics('api_response_time', Date.now() - 300000) // 最近5分钟\n .map((m) => m.value)\n .sort((a, b) => a - b);\n\n if (recentDurations.length > 0) {\n stats.p95 = recentDurations[Math.floor(recentDurations.length * 0.95)] || 0;\n stats.p99 = recentDurations[Math.floor(recentDurations.length * 0.99)] || 0;\n }\n }\n\n /**\n * 更新上传统计信息\n */\n private updateUploadStats(success: boolean, duration: number, fileSize?: number): void {\n const uploads = this.stats.fileOperations.uploads;\n uploads.total++;\n\n if (success) {\n uploads.successful++;\n } else {\n uploads.failed++;\n }\n\n // 更新平均上传时间\n uploads.averageTime = (uploads.averageTime * (uploads.total - 1) + duration) / uploads.total;\n\n // 更新平均文件大小\n if (fileSize) {\n uploads.averageSize = (uploads.averageSize * (uploads.total - 1) + fileSize) / uploads.total;\n }\n }\n\n /**\n * 更新下载统计信息\n */\n private updateDownloadStats(success: boolean, duration: number): void {\n const downloads = this.stats.fileOperations.downloads;\n downloads.total++;\n\n if (success) {\n downloads.successful++;\n } else {\n downloads.failed++;\n }\n\n // 更新平均下载时间\n downloads.averageTime =\n (downloads.averageTime * (downloads.total - 1) + duration) / downloads.total;\n }\n\n /**\n * 清理过期数据\n */\n private cleanupOldData(): void {\n const oneHourAgo = Date.now() - 3600000; // 1小时前\n\n // 清理过期指标\n this.metrics = this.metrics.filter((m) => m.timestamp > oneHourAgo);\n\n // 清理过期跟踪\n for (const [requestId, trace] of this.requestTraces.entries()) {\n if (trace.startTime < oneHourAgo) {\n this.requestTraces.delete(requestId);\n }\n }\n }\n\n /**\n * 重置统计信息\n */\n reset(): void {\n this.metrics = [];\n this.requestTraces.clear();\n this.stats = this.initializeStats();\n }\n}\n\n/**\n * 单例性能监控器实例\n */\nexport const performanceMonitor = new PerformanceMonitor();\n\n/**\n * 性能监控装饰器\n */\nexport function measurePerformance(operation: string) {\n return function (_target: any, _propertyName: string, descriptor: PropertyDescriptor) {\n const method = descriptor.value;\n\n descriptor.value = async function (...args: any[]) {\n const requestId = `${operation}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n try {\n performanceMonitor.startRequest(requestId, operation, 'INTERNAL');\n const result = await method.apply(this, args);\n performanceMonitor.endRequest(requestId, 200);\n return result;\n } catch (error) {\n performanceMonitor.endRequest(\n requestId,\n 500,\n error instanceof Error ? error.message : String(error)\n );\n throw error;\n }\n };\n\n return descriptor;\n };\n}\n","/**\n * CDN缓存策略管理\n * 优化静态资源缓存策略和预热机制\n */\n\n/**\n * 缓存策略类型\n */\nexport enum CacheStrategyType {\n /** 图片资源 */\n IMAGE = 'image',\n /** 视频资源 */\n VIDEO = 'video',\n /** 音频资源 */\n AUDIO = 'audio',\n /** 文档资源 */\n DOCUMENT = 'document',\n /** 压缩包 */\n ARCHIVE = 'archive',\n /** 静态资源 */\n STATIC = 'static',\n /** 其他 */\n OTHER = 'other',\n}\n\n/**\n * 缓存策略配置\n */\ninterface CacheStrategyConfig {\n /** 缓存策略类型 */\n type: CacheStrategyType;\n /** 缓存时间(秒) */\n ttl: number;\n /** 是否启用浏览器缓存 */\n browserCache: boolean;\n /** 浏览器缓存时间(秒) */\n browserCacheTtl: number;\n /** 是否启用CDN缓存 */\n cdnCache: boolean;\n /** CDN缓存时间(秒) */\n cdnCacheTtl: number;\n /** 是否启用预热 */\n enableWarmup: boolean;\n /** 缓存控制头 */\n cacheControl: string;\n /** 允许的文件类型 */\n allowedMimeTypes: string[];\n /** 文件大小限制(字节) */\n maxFileSize?: number;\n}\n\n/**\n * 缓存统计信息\n */\ninterface CacheStats {\n /** 命中次数 */\n hits: number;\n /** 未命中次数 */\n misses: number;\n /** 命中率 */\n hitRate: number;\n /** 总请求数 */\n totalRequests: number;\n /** 缓存大小估算 */\n estimatedSize: number;\n /** 节省的带宽(字节) */\n bandwidthSaved: number;\n}\n\n/**\n * CDN缓存策略管理器\n */\nexport class CdnCacheStrategy {\n private strategies: Map<CacheStrategyType, CacheStrategyConfig> = new Map();\n private stats: Map<CacheStrategyType, CacheStats> = new Map();\n\n constructor() {\n this.initializeDefaultStrategies();\n }\n\n /**\n * 初始化默认缓存策略\n */\n private initializeDefaultStrategies(): void {\n // 图片缓存策略\n this.strategies.set(CacheStrategyType.IMAGE, {\n type: CacheStrategyType.IMAGE,\n ttl: 30 * 24 * 3600, // 30天\n browserCache: true,\n browserCacheTtl: 7 * 24 * 3600, // 7天\n cdnCache: true,\n cdnCacheTtl: 30 * 24 * 3600, // 30天\n enableWarmup: true,\n cacheControl: 'public, max-age=604800, s-maxage=2592000',\n allowedMimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'],\n maxFileSize: 50 * 1024 * 1024, // 50MB\n });\n\n // 视频缓存策略\n this.strategies.set(CacheStrategyType.VIDEO, {\n type: CacheStrategyType.VIDEO,\n ttl: 7 * 24 * 3600, // 7天\n browserCache: true,\n browserCacheTtl: 24 * 3600, // 1天\n cdnCache: true,\n cdnCacheTtl: 7 * 24 * 3600, // 7天\n enableWarmup: false, // 视频文件通常较大,不预热\n cacheControl: 'public, max-age=86400, s-maxage=604800',\n allowedMimeTypes: ['video/mp4', 'video/avi', 'video/mov', 'video/wmv', 'video/webm'],\n maxFileSize: 500 * 1024 * 1024, // 500MB\n });\n\n // 音频缓存策略\n this.strategies.set(CacheStrategyType.AUDIO, {\n type: CacheStrategyType.AUDIO,\n ttl: 14 * 24 * 3600, // 14天\n browserCache: true,\n browserCacheTtl: 3 * 24 * 3600, // 3天\n cdnCache: true,\n cdnCacheTtl: 14 * 24 * 3600, // 14天\n enableWarmup: true,\n cacheControl: 'public, max-age=259200, s-maxage=1209600',\n allowedMimeTypes: ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/m4a', 'audio/flac'],\n maxFileSize: 100 * 1024 * 1024, // 100MB\n });\n\n // 文档缓存策略\n this.strategies.set(CacheStrategyType.DOCUMENT, {\n type: CacheStrategyType.DOCUMENT,\n ttl: 24 * 3600, // 1天\n browserCache: true,\n browserCacheTtl: 3600, // 1小时\n cdnCache: true,\n cdnCacheTtl: 24 * 3600, // 1天\n enableWarmup: false,\n cacheControl: 'public, max-age=3600, s-maxage=86400',\n allowedMimeTypes: [\n 'application/pdf',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/plain',\n 'text/csv',\n ],\n maxFileSize: 50 * 1024 * 1024, // 50MB\n });\n\n // 压缩包缓存策略\n this.strategies.set(CacheStrategyType.ARCHIVE, {\n type: CacheStrategyType.ARCHIVE,\n ttl: 24 * 3600, // 1天\n browserCache: true,\n browserCacheTtl: 1800, // 30分钟\n cdnCache: true,\n cdnCacheTtl: 24 * 3600, // 1天\n enableWarmup: false,\n cacheControl: 'public, max-age=1800, s-maxage=86400',\n allowedMimeTypes: [\n 'application/zip',\n 'application/x-rar-compressed',\n 'application/x-7z-compressed',\n 'application/gzip',\n 'application/x-tar',\n ],\n maxFileSize: 100 * 1024 * 1024, // 100MB\n });\n\n // 静态资源缓存策略\n this.strategies.set(CacheStrategyType.STATIC, {\n type: CacheStrategyType.STATIC,\n ttl: 365 * 24 * 3600, // 1年\n browserCache: true,\n browserCacheTtl: 30 * 24 * 3600, // 30天\n cdnCache: true,\n cdnCacheTtl: 365 * 24 * 3600, // 1年\n enableWarmup: true,\n cacheControl: 'public, max-age=2592000, s-maxage=31536000, immutable',\n allowedMimeTypes: [\n 'text/css',\n 'application/javascript',\n 'application/json',\n 'font/woff',\n 'font/woff2',\n 'font/ttf',\n ],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n });\n\n // 其他文件缓存策略\n this.strategies.set(CacheStrategyType.OTHER, {\n type: CacheStrategyType.OTHER,\n ttl: 3600, // 1小时\n browserCache: true,\n browserCacheTtl: 300, // 5分钟\n cdnCache: false,\n cdnCacheTtl: 0,\n enableWarmup: false,\n cacheControl: 'public, max-age=300',\n allowedMimeTypes: [],\n maxFileSize: 10 * 1024 * 1024, // 10MB\n });\n\n // 初始化统计信息\n for (const type of Object.values(CacheStrategyType)) {\n this.stats.set(type, {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n });\n }\n }\n\n /**\n * 根据MIME类型获取缓存策略\n */\n getStrategyByMimeType(mimeType: string): CacheStrategyConfig {\n for (const [type, strategy] of this.strategies.entries()) {\n if (strategy.allowedMimeTypes.includes(mimeType)) {\n return strategy;\n }\n }\n\n // 根据MIME类型推断策略\n if (mimeType.startsWith('image/')) {\n return this.strategies.get(CacheStrategyType.IMAGE)!;\n } else if (mimeType.startsWith('video/')) {\n return this.strategies.get(CacheStrategyType.VIDEO)!;\n } else if (mimeType.startsWith('audio/')) {\n return this.strategies.get(CacheStrategyType.AUDIO)!;\n } else if (\n mimeType.includes('pdf') ||\n mimeType.includes('document') ||\n mimeType.includes('word') ||\n mimeType.includes('excel')\n ) {\n return this.strategies.get(CacheStrategyType.DOCUMENT)!;\n } else if (\n mimeType.includes('zip') ||\n mimeType.includes('compressed') ||\n mimeType.includes('archive')\n ) {\n return this.strategies.get(CacheStrategyType.ARCHIVE)!;\n }\n\n return this.strategies.get(CacheStrategyType.OTHER)!;\n }\n\n /**\n * 生成缓存控制头\n */\n generateCacheHeaders(mimeType: string, fileSize?: number): Record<string, string> {\n const strategy = this.getStrategyByMimeType(mimeType);\n\n // 检查文件大小限制\n if (fileSize && strategy.maxFileSize && fileSize > strategy.maxFileSize) {\n // 大文件使用更短的缓存时间\n return {\n 'Cache-Control': 'public, max-age=300', // 5分钟\n Expires: new Date(Date.now() + 300 * 1000).toUTCString(),\n };\n }\n\n const headers: Record<string, string> = {\n 'Cache-Control': strategy.cacheControl,\n Expires: new Date(Date.now() + strategy.browserCacheTtl * 1000).toUTCString(),\n };\n\n // 添加ETag用于缓存验证\n if (strategy.browserCache) {\n headers['ETag'] = `\"${Date.now()}\"`;\n }\n\n // 添加Last-Modified头\n headers['Last-Modified'] = new Date().toUTCString();\n\n // 为静态资源添加不可变标记\n if (strategy.type === CacheStrategyType.STATIC) {\n headers['Cache-Control'] += ', immutable';\n }\n\n return headers;\n }\n\n /**\n * 检查是否需要缓存预热\n */\n shouldWarmupCache(mimeType: string): boolean {\n const strategy = this.getStrategyByMimeType(mimeType);\n return strategy.enableWarmup;\n }\n\n /**\n * 记录缓存命中\n */\n recordCacheHit(mimeType: string, fileSize: number = 0): void {\n const strategy = this.getStrategyByMimeType(mimeType);\n const stats = this.stats.get(strategy.type);\n\n if (stats) {\n stats.hits++;\n stats.totalRequests++;\n stats.bandwidthSaved += fileSize;\n stats.hitRate = (stats.hits / stats.totalRequests) * 100;\n }\n }\n\n /**\n * 记录缓存未命中\n */\n recordCacheMiss(mimeType: string, fileSize: number = 0): void {\n const strategy = this.getStrategyByMimeType(mimeType);\n const stats = this.stats.get(strategy.type);\n\n if (stats) {\n stats.misses++;\n stats.totalRequests++;\n stats.estimatedSize += fileSize;\n stats.hitRate = (stats.hits / stats.totalRequests) * 100;\n }\n }\n\n /**\n * 获取缓存统计信息\n */\n getCacheStats(): Map<CacheStrategyType, CacheStats> {\n return new Map(this.stats);\n }\n\n /**\n * 获取总体缓存统计\n */\n getOverallStats(): CacheStats {\n const overall: CacheStats = {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n };\n\n for (const stats of this.stats.values()) {\n overall.hits += stats.hits;\n overall.misses += stats.misses;\n overall.totalRequests += stats.totalRequests;\n overall.estimatedSize += stats.estimatedSize;\n overall.bandwidthSaved += stats.bandwidthSaved;\n }\n\n overall.hitRate = overall.totalRequests > 0 ? (overall.hits / overall.totalRequests) * 100 : 0;\n\n return overall;\n }\n\n /**\n * 生成缓存优化建议\n */\n generateOptimizationSuggestions(): Array<{\n type: CacheStrategyType;\n issue: string;\n suggestion: string;\n severity: 'low' | 'medium' | 'high';\n }> {\n const suggestions: Array<{\n type: CacheStrategyType;\n issue: string;\n suggestion: string;\n severity: 'low' | 'medium' | 'high';\n }> = [];\n\n for (const [type, stats] of this.stats.entries()) {\n if (stats.totalRequests > 100) {\n // 只对有足够请求量的资源类型分析\n // 命中率过低\n if (stats.hitRate < 60) {\n suggestions.push({\n type,\n issue: `${type}类型文件缓存命中率过低 (${stats.hitRate.toFixed(1)}%)`,\n suggestion: '考虑增加缓存时间或启用预热机制',\n severity: stats.hitRate < 30 ? 'high' : 'medium',\n });\n }\n\n // 缓存大小过大\n if (stats.estimatedSize > 1024 * 1024 * 1024) {\n // 1GB\n suggestions.push({\n type,\n issue: `${type}类型文件缓存占用空间过大 (${(stats.estimatedSize / 1024 / 1024 / 1024).toFixed(2)}GB)`,\n suggestion: '考虑减少缓存时间或优化文件压缩',\n severity: 'medium',\n });\n }\n }\n }\n\n return suggestions;\n }\n\n /**\n * 更新缓存策略\n */\n updateStrategy(type: CacheStrategyType, config: Partial<CacheStrategyConfig>): void {\n const currentStrategy = this.strategies.get(type);\n if (currentStrategy) {\n this.strategies.set(type, { ...currentStrategy, ...config });\n }\n }\n\n /**\n * 重置统计信息\n */\n resetStats(): void {\n for (const type of Object.values(CacheStrategyType)) {\n this.stats.set(type, {\n hits: 0,\n misses: 0,\n hitRate: 0,\n totalRequests: 0,\n estimatedSize: 0,\n bandwidthSaved: 0,\n });\n }\n }\n}\n\n/**\n * 单例CDN缓存策略管理器\n */\nexport const cdnCacheStrategy = new CdnCacheStrategy();\n","/**\n * 通用文件服务 API 类型定义\n * 定义所有API接口的请求和响应格式\n */\n\n// ========== 基础响应格式 ==========\n\n/**\n * API响应的基础接口\n */\nexport interface ApiResponse<T = any> {\n /** 是否成功 */\n success: boolean;\n /** 响应数据 */\n data?: T;\n /** 错误信息 */\n error?: {\n /** 错误代码 */\n code: string;\n /** 错误消息 */\n message: string;\n /** 详细错误信息 */\n details?: any;\n };\n /** 元数据 */\n meta?: {\n /** 总记录数 */\n total?: number;\n /** 当前页码 */\n page?: number;\n /** 每页大小 */\n pageSize?: number;\n /** 总页数 */\n totalPages?: number;\n /** 请求ID */\n requestId?: string;\n /** 时间戳 */\n timestamp?: string;\n };\n}\n\n/**\n * 分页查询参数\n */\nexport interface PaginationParams {\n /** 页码,从1开始 */\n page?: number;\n /** 每页大小 */\n pageSize?: number;\n /** 排序字段 */\n orderBy?: string;\n /** 排序方向 */\n orderDirection?: 'asc' | 'desc';\n}\n\n/**\n * 文件上传响应\n */\nexport interface UploadResponse {\n /** 文件ID */\n fileId: string;\n /** 原始文件名 */\n originalName: string;\n /** 文件大小 */\n size: number;\n /** MIME类型 */\n mimeType: string;\n /** 访问URL */\n url: string;\n /** CDN URL */\n cdnUrl?: string;\n /** MD5哈希 */\n md5Hash: string;\n /** 上传时间 */\n uploadTime: string;\n}\n\n// ========== 文件管理API ==========\n\n/**\n * 文件上传请求参数\n */\nexport interface FileUploadParams {\n /** 目标文件夹ID */\n folderId?: string;\n /** 模块ID */\n moduleId?: string;\n /** 业务ID */\n businessId?: string;\n /** 文件标签 */\n tags?: string[];\n /** 是否为临时文件 */\n isTemporary?: boolean;\n /** 过期时间 */\n expiresAt?: string;\n /** 自定义元数据 */\n metadata?: Record<string, any>;\n}\n\n/**\n * 文件查询参数\n */\nexport interface FileQueryParams extends PaginationParams {\n /** 模块ID */\n moduleId?: string;\n /** 业务ID */\n businessId?: string;\n /** 文件夹ID */\n folderId?: string;\n /** MIME类型过滤 */\n mimeType?: string;\n /** 文件名搜索 */\n search?: string;\n /** 标签过滤 */\n tags?: string[];\n /** 文件大小范围 */\n sizeMin?: number;\n sizeMax?: number;\n /** 上传时间范围 */\n uploadTimeStart?: string;\n uploadTimeEnd?: string;\n /** 是否已删除 */\n isDeleted?: boolean;\n /** 是否临时文件 */\n isTemporary?: boolean;\n /** 上传者ID */\n uploaderId?: string;\n}\n\n/**\n * 文件信息响应\n */\nexport interface FileInfo {\n /** 文件ID */\n id: string;\n /** 原始文件名 */\n originalName: string;\n /** 存储文件名 */\n storedName: string;\n /** 文件扩展名 */\n extension?: string;\n /** MIME类型 */\n mimeType: string;\n /** 文件大小 */\n size: number;\n /** MD5哈希 */\n md5Hash: string;\n /** SHA256哈希 */\n sha256Hash?: string;\n /** 存储路径 */\n storagePath: string;\n /** CDN访问URL */\n cdnUrl?: string;\n /** 所属文件夹ID */\n folderId?: string;\n /** 模块ID */\n moduleId?: string;\n /** 业务ID */\n businessId?: string;\n /** 文件标签 */\n tags?: string[];\n /** 文件元信息 */\n metadata?: Record<string, any>;\n /** 是否为临时文件 */\n isTemporary: boolean;\n /** 是否已删除 */\n isDeleted: boolean;\n /** 访问次数 */\n accessCount: number;\n /** 下载次数 */\n downloadCount: number;\n /** 上传者ID */\n uploaderId: string;\n /** 上传时间 */\n uploadTime: string;\n /** 最后访问时间 */\n lastAccessTime?: string;\n /** 过期时间 */\n expiresAt?: string;\n /** 创建时间 */\n createdAt: string;\n /** 更新时间 */\n updatedAt: string;\n}\n\n/**\n * 文件列表响应\n */\nexport interface FileListResponse {\n /** 文件列表 */\n files: FileInfo[];\n /** 分页信息 */\n pagination: {\n /** 总记录数 */\n total: number;\n /** 当前页码 */\n page: number;\n /** 每页大小 */\n pageSize: number;\n /** 总页数 */\n totalPages: number;\n };\n}\n\n/**\n * 文件更新参数\n */\nexport interface FileUpdateParams {\n /** 新的文件名 */\n originalName?: string;\n /** 文件夹ID */\n folderId?: string;\n /** 文件标签 */\n tags?: string[];\n /** 自定义元数据 */\n metadata?: Record<string, any>;\n /** 过期时间 */\n expiresAt?: string;\n}\n\n// ========== 文件夹管理API ==========\n\n/**\n * 文件夹创建参数\n */\nexport interface FolderCreateParams {\n /** 文件夹名称 */\n name: string;\n /** 父文件夹ID */\n parentId?: string;\n /** 模块ID */\n moduleId?: string;\n /** 业务ID */\n businessId?: string;\n /** 文件夹描述 */\n description?: string;\n /** 显示顺序 */\n sortOrder?: number;\n}\n\n/**\n * 文件夹信息响应\n */\nexport interface FolderInfo {\n /** 文件夹ID */\n id: string;\n /** 文件夹名称 */\n name: string;\n /** 父文件夹ID */\n parentId?: string;\n /** 模块ID */\n moduleId?: string;\n /** 业务ID */\n businessId?: string;\n /** 文件夹路径 */\n path: string;\n /** 层级深度 */\n depth: number;\n /** 显示顺序 */\n sortOrder: number;\n /** 文件夹描述 */\n description?: string;\n /** 是否为系统文件夹 */\n isSystem: boolean;\n /** 创建者ID */\n createdBy: string;\n /** 创建时间 */\n createdAt: string;\n /** 更新时间 */\n updatedAt: string;\n /** 子文件夹列表 */\n children?: FolderInfo[];\n /** 文件数量 */\n fileCount?: number;\n}\n\n/**\n * 文件夹更新参数\n */\nexport interface FolderUpdateParams {\n /** 文件夹名称 */\n name?: string;\n /** 父文件夹ID */\n parentId?: string;\n /** 文件夹描述 */\n description?: string;\n /** 显示顺序 */\n sortOrder?: number;\n}\n\n// ========== 文件处理API ==========\n\n/**\n * 文件处理请求参数\n */\nexport interface FileProcessParams {\n /** 处理类型 */\n type: 'compress' | 'resize' | 'convert' | 'thumbnail' | 'watermark';\n /** 处理参数 */\n parameters: Record<string, any>;\n /** 优先级 */\n priority?: number;\n}\n\n/**\n * 文件处理状态响应\n */\nexport interface ProcessingStatus {\n /** 处理记录ID */\n id: string;\n /** 文件ID */\n fileId: string;\n /** 处理类型 */\n type: string;\n /** 处理状态 */\n status: 'pending' | 'processing' | 'completed' | 'failed';\n /** 处理进度 */\n progress?: number;\n /** 处理参数 */\n parameters?: Record<string, any>;\n /** 处理结果 */\n result?: Record<string, any>;\n /** 输出文件路径 */\n outputPath?: string;\n /** 错误信息 */\n errorMessage?: string;\n /** 开始时间 */\n startedAt?: string;\n /** 完成时间 */\n completedAt?: string;\n /** 创建时间 */\n createdAt: string;\n}\n\n// ========== 文件分享API ==========\n\n/**\n * 文件分享创建参数\n */\nexport interface ShareCreateParams {\n /** 分享的文件ID列表 */\n fileIds: string[];\n /** 分享标题 */\n title?: string;\n /** 分享描述 */\n description?: string;\n /** 访问密码 */\n password?: string;\n /** 访问权限 */\n permission?: 'view' | 'download';\n /** 最大下载次数 */\n maxDownloads?: number;\n /** 最大访问次数 */\n maxAccess?: number;\n /** 过期时间 */\n expiresAt?: string;\n}\n\n/**\n * 文件分享信息响应\n */\nexport interface ShareInfo {\n /** 分享ID */\n id: string;\n /** 分享代码 */\n shareCode: string;\n /** 分享的文件ID列表 */\n fileIds: string[];\n /** 分享标题 */\n title?: string;\n /** 分享描述 */\n description?: string;\n /** 是否有密码保护 */\n hasPassword: boolean;\n /** 访问权限 */\n permission: 'view' | 'download';\n /** 最大下载次数 */\n maxDownloads?: number;\n /** 当前下载次数 */\n downloadCount: number;\n /** 最大访问次数 */\n maxAccess?: number;\n /** 当前访问次数 */\n accessCount: number;\n /** 是否启用 */\n isActive: boolean;\n /** 过期时间 */\n expiresAt?: string;\n /** 创建者ID */\n createdBy: string;\n /** 创建时间 */\n createdAt: string;\n /** 分享链接 */\n shareUrl: string;\n}\n\n/**\n * 分享访问验证参数\n */\nexport interface ShareAccessParams {\n /** 分享代码 */\n shareCode: string;\n /** 访问密码 */\n password?: string;\n}\n\n// ========== 统计API ==========\n\n/**\n * 文件统计信息响应\n */\nexport interface FileStats {\n /** 总文件数 */\n totalFiles: number;\n /** 总文件大小 */\n totalSize: number;\n /** 按类型统计 */\n byType: Array<{\n /** MIME类型 */\n mimeType: string;\n /** 文件数量 */\n count: number;\n /** 总大小 */\n totalSize: number;\n }>;\n /** 按日期统计(最近30天) */\n byDate: Array<{\n /** 日期 */\n date: string;\n /** 上传数量 */\n count: number;\n /** 总大小 */\n totalSize: number;\n }>;\n /** 按模块统计 */\n byModule: Array<{\n /** 模块ID */\n moduleId: string;\n /** 文件数量 */\n count: number;\n /** 总大小 */\n totalSize: number;\n }>;\n}\n\n// ========== 错误代码定义 ==========\n\n/**\n * API错误代码枚举\n */\nexport enum ApiErrorCode {\n // 通用错误\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n VALIDATION_ERROR = 'VALIDATION_ERROR',\n AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR',\n AUTHORIZATION_ERROR = 'AUTHORIZATION_ERROR',\n NOT_FOUND = 'NOT_FOUND',\n CONFLICT = 'CONFLICT',\n RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',\n\n // 文件相关错误\n FILE_NOT_FOUND = 'FILE_NOT_FOUND',\n FILE_TOO_LARGE = 'FILE_TOO_LARGE',\n FILE_TYPE_NOT_SUPPORTED = 'FILE_TYPE_NOT_SUPPORTED',\n FILE_UPLOAD_FAILED = 'FILE_UPLOAD_FAILED',\n FILE_PROCESSING_FAILED = 'FILE_PROCESSING_FAILED',\n FILE_ALREADY_EXISTS = 'FILE_ALREADY_EXISTS',\n FILE_CORRUPTED = 'FILE_CORRUPTED',\n\n // 文件夹相关错误\n FOLDER_NOT_FOUND = 'FOLDER_NOT_FOUND',\n FOLDER_NOT_EMPTY = 'FOLDER_NOT_EMPTY',\n FOLDER_NAME_CONFLICT = 'FOLDER_NAME_CONFLICT',\n FOLDER_DEPTH_EXCEEDED = 'FOLDER_DEPTH_EXCEEDED',\n\n // 存储相关错误\n STORAGE_PROVIDER_ERROR = 'STORAGE_PROVIDER_ERROR',\n STORAGE_QUOTA_EXCEEDED = 'STORAGE_QUOTA_EXCEEDED',\n STORAGE_UNAVAILABLE = 'STORAGE_UNAVAILABLE',\n\n // 分享相关错误\n SHARE_NOT_FOUND = 'SHARE_NOT_FOUND',\n SHARE_EXPIRED = 'SHARE_EXPIRED',\n SHARE_PASSWORD_INCORRECT = 'SHARE_PASSWORD_INCORRECT',\n SHARE_ACCESS_DENIED = 'SHARE_ACCESS_DENIED',\n SHARE_DOWNLOAD_LIMIT_EXCEEDED = 'SHARE_DOWNLOAD_LIMIT_EXCEEDED',\n}\n\n/**\n * 错误消息映射\n */\nexport const ErrorMessages: Record<ApiErrorCode, string> = {\n [ApiErrorCode.UNKNOWN_ERROR]: '未知错误',\n [ApiErrorCode.VALIDATION_ERROR]: '参数验证失败',\n [ApiErrorCode.AUTHENTICATION_ERROR]: '身份验证失败',\n [ApiErrorCode.AUTHORIZATION_ERROR]: '权限不足',\n [ApiErrorCode.NOT_FOUND]: '资源不存在',\n [ApiErrorCode.CONFLICT]: '资源冲突',\n [ApiErrorCode.RATE_LIMIT_EXCEEDED]: '请求频率超限',\n\n [ApiErrorCode.FILE_NOT_FOUND]: '文件不存在',\n [ApiErrorCode.FILE_TOO_LARGE]: '文件过大',\n [ApiErrorCode.FILE_TYPE_NOT_SUPPORTED]: '不支持的文件类型',\n [ApiErrorCode.FILE_UPLOAD_FAILED]: '文件上传失败',\n [ApiErrorCode.FILE_PROCESSING_FAILED]: '文件处理失败',\n [ApiErrorCode.FILE_ALREADY_EXISTS]: '文件已存在',\n [ApiErrorCode.FILE_CORRUPTED]: '文件已损坏',\n\n [ApiErrorCode.FOLDER_NOT_FOUND]: '文件夹不存在',\n [ApiErrorCode.FOLDER_NOT_EMPTY]: '文件夹不为空',\n [ApiErrorCode.FOLDER_NAME_CONFLICT]: '文件夹名称冲突',\n [ApiErrorCode.FOLDER_DEPTH_EXCEEDED]: '文件夹层级过深',\n\n [ApiErrorCode.STORAGE_PROVIDER_ERROR]: '存储服务错误',\n [ApiErrorCode.STORAGE_QUOTA_EXCEEDED]: '存储配额已满',\n [ApiErrorCode.STORAGE_UNAVAILABLE]: '存储服务不可用',\n\n [ApiErrorCode.SHARE_NOT_FOUND]: '分享不存在',\n [ApiErrorCode.SHARE_EXPIRED]: '分享已过期',\n [ApiErrorCode.SHARE_PASSWORD_INCORRECT]: '分享密码错误',\n [ApiErrorCode.SHARE_ACCESS_DENIED]: '分享访问被拒绝',\n [ApiErrorCode.SHARE_DOWNLOAD_LIMIT_EXCEEDED]: '分享下载次数已达上限',\n};\n\n// ========== HTTP状态码映射 ==========\n\n/**\n * 错误代码到HTTP状态码的映射\n */\nexport const ErrorHttpStatusMap: Record<ApiErrorCode, number> = {\n [ApiErrorCode.UNKNOWN_ERROR]: 500,\n [ApiErrorCode.VALIDATION_ERROR]: 400,\n [ApiErrorCode.AUTHENTICATION_ERROR]: 401,\n [ApiErrorCode.AUTHORIZATION_ERROR]: 403,\n [ApiErrorCode.NOT_FOUND]: 404,\n [ApiErrorCode.CONFLICT]: 409,\n [ApiErrorCode.RATE_LIMIT_EXCEEDED]: 429,\n\n [ApiErrorCode.FILE_NOT_FOUND]: 404,\n [ApiErrorCode.FILE_TOO_LARGE]: 413,\n [ApiErrorCode.FILE_TYPE_NOT_SUPPORTED]: 415,\n [ApiErrorCode.FILE_UPLOAD_FAILED]: 500,\n [ApiErrorCode.FILE_PROCESSING_FAILED]: 500,\n [ApiErrorCode.FILE_ALREADY_EXISTS]: 409,\n [ApiErrorCode.FILE_CORRUPTED]: 422,\n\n [ApiErrorCode.FOLDER_NOT_FOUND]: 404,\n [ApiErrorCode.FOLDER_NOT_EMPTY]: 409,\n [ApiErrorCode.FOLDER_NAME_CONFLICT]: 409,\n [ApiErrorCode.FOLDER_DEPTH_EXCEEDED]: 400,\n\n [ApiErrorCode.STORAGE_PROVIDER_ERROR]: 502,\n [ApiErrorCode.STORAGE_QUOTA_EXCEEDED]: 507,\n [ApiErrorCode.STORAGE_UNAVAILABLE]: 503,\n\n [ApiErrorCode.SHARE_NOT_FOUND]: 404,\n [ApiErrorCode.SHARE_EXPIRED]: 410,\n [ApiErrorCode.SHARE_PASSWORD_INCORRECT]: 401,\n [ApiErrorCode.SHARE_ACCESS_DENIED]: 403,\n [ApiErrorCode.SHARE_DOWNLOAD_LIMIT_EXCEEDED]: 429,\n};\n","// @ts-nocheck\n/**\n * API错误处理工具类\n * 提供标准化的错误处理和响应格式\n */\n\nimport { NextResponse } from 'next/server';\nimport { ApiResponse, ApiErrorCode, ErrorMessages, ErrorHttpStatusMap } from '../types/api';\n\n/**\n * API错误类\n * 继承自Error,添加错误代码和详细信息\n */\nexport class ApiError extends Error {\n public readonly code: ApiErrorCode;\n public readonly statusCode: number;\n public readonly details?: any;\n\n constructor(code: ApiErrorCode, message?: string, details?: any, statusCode?: number) {\n super(message || ErrorMessages[code]);\n this.name = 'ApiError';\n this.code = code;\n this.statusCode = statusCode || ErrorHttpStatusMap[code] || 500;\n this.details = details;\n\n // 确保错误堆栈正确显示\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ApiError);\n }\n }\n\n /**\n * 转换为API响应格式\n */\n toApiResponse(): ApiResponse {\n return {\n success: false,\n error: {\n code: this.code,\n message: this.message,\n details: this.details,\n },\n meta: {\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n /**\n * 转换为NextResponse\n */\n toNextResponse(): NextResponse {\n return NextResponse.json(this.toApiResponse(), {\n status: this.statusCode,\n });\n }\n}\n\n/**\n * API错误工厂类\n * 提供便捷的错误创建方法\n */\nexport class ApiErrorFactory {\n /**\n * 创建文件不存在错误\n */\n static fileNotFound(fileId?: string): ApiError {\n return new ApiError(ApiErrorCode.FILE_NOT_FOUND, undefined, { fileId });\n }\n\n /**\n * 创建文件过大错误\n */\n static fileTooLarge(maxSize: number, actualSize: number): ApiError {\n return new ApiError(\n ApiErrorCode.FILE_TOO_LARGE,\n `文件大小 ${actualSize} 字节超过限制 ${maxSize} 字节`,\n { maxSize, actualSize }\n );\n }\n\n /**\n * 创建不支持的文件类型错误\n */\n static fileTypeNotSupported(mimeType: string, supportedTypes?: string[]): ApiError {\n return new ApiError(ApiErrorCode.FILE_TYPE_NOT_SUPPORTED, `不支持的文件类型: ${mimeType}`, {\n mimeType,\n supportedTypes,\n });\n }\n\n /**\n * 创建文件上传失败错误\n */\n static fileUploadFailed(reason?: string): ApiError {\n return new ApiError(\n ApiErrorCode.FILE_UPLOAD_FAILED,\n reason ? `文件上传失败: ${reason}` : undefined,\n { reason }\n );\n }\n\n /**\n * 创建文件夹不存在错误\n */\n static folderNotFound(folderId?: string): ApiError {\n return new ApiError(ApiErrorCode.FOLDER_NOT_FOUND, undefined, { folderId });\n }\n\n /**\n * 创建文件夹不为空错误\n */\n static folderNotEmpty(folderId: string, fileCount: number, subfolderCount: number): ApiError {\n return new ApiError(\n ApiErrorCode.FOLDER_NOT_EMPTY,\n `文件夹包含 ${fileCount} 个文件和 ${subfolderCount} 个子文件夹`,\n { folderId, fileCount, subfolderCount }\n );\n }\n\n /**\n * 创建参数验证错误\n */\n static validationError(field: string, value: any, rule: string): ApiError {\n return new ApiError(ApiErrorCode.VALIDATION_ERROR, `字段 ${field} 验证失败: ${rule}`, {\n field,\n value,\n rule,\n });\n }\n\n /**\n * 创建身份验证错误\n */\n static authenticationError(reason?: string): ApiError {\n return new ApiError(\n ApiErrorCode.AUTHENTICATION_ERROR,\n reason ? `身份验证失败: ${reason}` : undefined,\n { reason }\n );\n }\n\n /**\n * 创建权限不足错误\n */\n static authorizationError(resource?: string, action?: string): ApiError {\n return new ApiError(\n ApiErrorCode.AUTHORIZATION_ERROR,\n resource && action ? `无权限对 ${resource} 执行 ${action} 操作` : undefined,\n { resource, action }\n );\n }\n\n /**\n * 创建资源冲突错误\n */\n static conflict(resource: string, reason?: string): ApiError {\n return new ApiError(\n ApiErrorCode.CONFLICT,\n reason ? `${resource} 冲突: ${reason}` : `${resource} 已存在`,\n { resource, reason }\n );\n }\n\n /**\n * 创建请求频率超限错误\n */\n static rateLimitExceeded(limit: number, windowMs: number): ApiError {\n return new ApiError(\n ApiErrorCode.RATE_LIMIT_EXCEEDED,\n `请求频率超限,${windowMs}ms 内最多允许 ${limit} 次请求`,\n { limit, windowMs }\n );\n }\n\n /**\n * 创建存储服务错误\n */\n static storageProviderError(provider: string, reason?: string): ApiError {\n return new ApiError(\n ApiErrorCode.STORAGE_PROVIDER_ERROR,\n reason ? `存储服务 ${provider} 错误: ${reason}` : `存储服务 ${provider} 不可用`,\n { provider, reason }\n );\n }\n\n /**\n * 创建存储配额已满错误\n */\n static storageQuotaExceeded(used: number, limit: number): ApiError {\n return new ApiError(\n ApiErrorCode.STORAGE_QUOTA_EXCEEDED,\n `存储空间已满,已使用 ${used} 字节,限制 ${limit} 字节`,\n { used, limit, remaining: Math.max(0, limit - used) }\n );\n }\n\n /**\n * 创建分享不存在错误\n */\n static shareNotFound(shareCode?: string): ApiError {\n return new ApiError(ApiErrorCode.SHARE_NOT_FOUND, undefined, { shareCode });\n }\n\n /**\n * 创建分享已过期错误\n */\n static shareExpired(shareCode: string, expiredAt: string): ApiError {\n return new ApiError(ApiErrorCode.SHARE_EXPIRED, `分享已于 ${expiredAt} 过期`, {\n shareCode,\n expiredAt,\n });\n }\n\n /**\n * 创建分享密码错误\n */\n static sharePasswordIncorrect(shareCode: string): ApiError {\n return new ApiError(ApiErrorCode.SHARE_PASSWORD_INCORRECT, undefined, { shareCode });\n }\n\n /**\n * 创建分享下载次数超限错误\n */\n static shareDownloadLimitExceeded(shareCode: string, maxDownloads: number): ApiError {\n return new ApiError(\n ApiErrorCode.SHARE_DOWNLOAD_LIMIT_EXCEEDED,\n `分享下载次数已达上限 ${maxDownloads} 次`,\n { shareCode, maxDownloads }\n );\n }\n}\n\n/**\n * API响应工具类\n * 提供标准化的成功响应格式\n */\nexport class ApiResponseHelper {\n /**\n * 创建成功响应\n */\n static success<T>(\n data?: T,\n meta?: {\n total?: number;\n page?: number;\n pageSize?: number;\n totalPages?: number;\n requestId?: string;\n }\n ): ApiResponse<T> {\n return {\n success: true,\n data,\n meta: {\n ...meta,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n /**\n * 创建分页响应\n */\n static paginated<T>(\n data: T[],\n total: number,\n page: number,\n pageSize: number,\n requestId?: string\n ): ApiResponse<{ items: T[]; pagination: any }> {\n const totalPages = Math.ceil(total / pageSize);\n\n return {\n success: true,\n data: {\n items: data,\n pagination: {\n total,\n page,\n pageSize,\n totalPages,\n hasNext: page < totalPages,\n hasPrev: page > 1,\n },\n },\n meta: {\n total,\n page,\n pageSize,\n totalPages,\n requestId,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n /**\n * 创建空响应\n */\n static empty(requestId?: string): ApiResponse<null> {\n return {\n success: true,\n data: null,\n meta: {\n requestId,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n /**\n * 转换为NextResponse\n */\n static toNextResponse<T>(response: ApiResponse<T>, status: number = 200): NextResponse {\n return NextResponse.json(response, { status });\n }\n}\n\n/**\n * 错误处理中间件装饰器\n */\nexport function withErrorHandler<T extends any[], R>(\n fn: (...args: T) => Promise<R>\n): (...args: T) => Promise<R> {\n return async (...args: T): Promise<R> => {\n try {\n return await fn(...args);\n } catch (error) {\n // 如果已经是ApiError,直接抛出\n if (error instanceof ApiError) {\n throw error;\n }\n\n // 处理常见的系统错误\n if (error instanceof Error) {\n // 数据库连接错误\n if (error.message.includes('connect') || error.message.includes('connection')) {\n throw new ApiError(ApiErrorCode.STORAGE_UNAVAILABLE, '数据库连接失败', {\n originalError: error.message,\n });\n }\n\n // 文件系统错误\n if (error.message.includes('ENOENT')) {\n throw new ApiError(ApiErrorCode.FILE_NOT_FOUND, '文件不存在', {\n originalError: error.message,\n });\n }\n\n if (error.message.includes('EACCES') || error.message.includes('permission')) {\n throw new ApiError(ApiErrorCode.AUTHORIZATION_ERROR, '文件权限不足', {\n originalError: error.message,\n });\n }\n\n if (error.message.includes('ENOSPC')) {\n throw new ApiError(ApiErrorCode.STORAGE_QUOTA_EXCEEDED, '磁盘空间不足', {\n originalError: error.message,\n });\n }\n }\n\n // 其他未知错误\n throw new ApiError(ApiErrorCode.UNKNOWN_ERROR, '服务器内部错误', {\n originalError: error instanceof Error ? error.message : String(error),\n });\n }\n };\n}\n\n/**\n * 异步错误处理包装器\n */\nexport function handleAsyncError(\n handler: (req: Request, ...args: any[]) => Promise<NextResponse>\n): (req: Request, ...args: any[]) => Promise<NextResponse> {\n return async (req: Request, ...args: any[]): Promise<NextResponse> => {\n try {\n return await handler(req, ...args);\n } catch (error) {\n console.error('API Error:', error);\n\n if (error instanceof ApiError) {\n return error.toNextResponse();\n }\n\n // 未知错误\n const apiError = new ApiError(ApiErrorCode.UNKNOWN_ERROR, '服务器内部错误', {\n originalError: error instanceof Error ? error.message : String(error),\n });\n\n return apiError.toNextResponse();\n }\n };\n}\n\n/**\n * 参数验证工具\n */\nexport class ValidationHelper {\n /**\n * 验证必填参数\n */\n static required(value: any, fieldName: string): void {\n if (value === undefined || value === null || value === '') {\n throw ApiErrorFactory.validationError(fieldName, value, '不能为空');\n }\n }\n\n /**\n * 验证字符串长度\n */\n static stringLength(value: string, fieldName: string, min?: number, max?: number): void {\n if (min !== undefined && value.length < min) {\n throw ApiErrorFactory.validationError(fieldName, value, `长度不能少于${min}个字符`);\n }\n if (max !== undefined && value.length > max) {\n throw ApiErrorFactory.validationError(fieldName, value, `长度不能超过${max}个字符`);\n }\n }\n\n /**\n * 验证数字范围\n */\n static numberRange(value: number, fieldName: string, min?: number, max?: number): void {\n if (min !== undefined && value < min) {\n throw ApiErrorFactory.validationError(fieldName, value, `不能小于${min}`);\n }\n if (max !== undefined && value > max) {\n throw ApiErrorFactory.validationError(fieldName, value, `不能大于${max}`);\n }\n }\n\n /**\n * 验证数组长度\n */\n static arrayLength(value: any[], fieldName: string, min?: number, max?: number): void {\n if (min !== undefined && value.length < min) {\n throw ApiErrorFactory.validationError(fieldName, value, `数组长度不能少于${min}`);\n }\n if (max !== undefined && value.length > max) {\n throw ApiErrorFactory.validationError(fieldName, value, `数组长度不能超过${max}`);\n }\n }\n\n /**\n * 验证文件类型\n */\n static fileType(mimeType: string, allowedTypes: string[]): void {\n if (!allowedTypes.includes(mimeType)) {\n throw ApiErrorFactory.fileTypeNotSupported(mimeType, allowedTypes);\n }\n }\n\n /**\n * 验证文件大小\n */\n static fileSize(size: number, maxSize: number): void {\n if (size > maxSize) {\n throw ApiErrorFactory.fileTooLarge(maxSize, size);\n }\n }\n\n /**\n * 验证UUID格式\n */\n static uuid(value: string, fieldName: string): void {\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n if (!uuidRegex.test(value)) {\n throw ApiErrorFactory.validationError(fieldName, value, '必须是有效的UUID格式');\n }\n }\n\n /**\n * 验证邮箱格式\n */\n static email(value: string, fieldName: string): void {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(value)) {\n throw ApiErrorFactory.validationError(fieldName, value, '必须是有效的邮箱格式');\n }\n }\n\n /**\n * 验证URL格式\n */\n static url(value: string, fieldName: string): void {\n try {\n new URL(value);\n } catch {\n throw ApiErrorFactory.validationError(fieldName, value, '必须是有效的URL格式');\n }\n }\n}\n","// @ts-nocheck\n/**\n * Drizzle ORM 文件元数据持久化适配器\n *\n * 提供基于 Drizzle ORM 的数据库持久化实现\n */\n\nimport { eq, and, desc, sql, SQL } from 'drizzle-orm';\nimport type { FileMetadata, FileQueryOptions, PaginatedResult } from '../../types';\nimport type { IFileMetadataRepository } from '../types';\nimport { createLogger } from '../../../logger';\n\nconst logger = createLogger('DrizzleFileRepository');\n\n/**\n * Drizzle 表定义类型(兼容多种 Drizzle 表结构)\n */\nexport type DrizzleTable = any;\n\n/**\n * Drizzle 数据库连接类型\n */\nexport type DrizzleDb = any;\n\n/**\n * 字段映射配置\n *\n * 将 FileMetadata 的字段映射到数据库表的列名\n */\nexport interface FieldMapping {\n id?: string;\n filename?: string;\n originalName?: string;\n mimeType?: string;\n size?: string;\n hash?: string;\n storageType?: string;\n storagePath?: string;\n url?: string;\n cdnUrl?: string;\n moduleId?: string;\n businessId?: string;\n userId?: string;\n uploadedAt?: string;\n expiresAt?: string;\n metadata?: string;\n status?: string;\n processingStatus?: string;\n versions?: string;\n tags?: string;\n}\n\n/**\n * Drizzle 仓储配置\n */\nexport interface DrizzleRepositoryConfig {\n /** Drizzle 数据库实例 */\n db: DrizzleDb;\n /** 文件元数据表 */\n table: DrizzleTable;\n /** 字段映射(如果数据库列名与 FileMetadata 字段不同) */\n fieldMapping?: FieldMapping;\n}\n\n/**\n * 创建 Drizzle ORM 文件仓储\n *\n * @example\n * ```typescript\n * import { createDrizzleRepository } from '@qhr123/sa2kit/universalFile/server';\n * import { db } from './db';\n * import { fileMetadata } from './schema';\n *\n * const repository = createDrizzleRepository({\n * db,\n * table: fileMetadata,\n * fieldMapping: {\n * // 如果列名与 FileMetadata 字段不同,可以在这里映射\n * originalName: 'original_filename',\n * }\n * });\n * ```\n */\nexport function createDrizzleRepository(config: DrizzleRepositoryConfig): IFileMetadataRepository {\n const { db, table, fieldMapping = {} } = config;\n\n /**\n * 获取字段名(考虑映射)\n */\n const getField = (field: keyof FieldMapping): string => {\n return (fieldMapping[field] || field) as string;\n };\n\n /**\n * 将 FileMetadata 转换为数据库记录\n */\n const toDbRecord = (metadata: FileMetadata): any => {\n const record: any = {\n [getField('id')]: metadata.id,\n [getField('filename')]: metadata.filename,\n [getField('originalName')]: metadata.originalName,\n [getField('mimeType')]: metadata.mimeType,\n [getField('size')]: metadata.size,\n [getField('storageType')]: metadata.storageType,\n [getField('storagePath')]: metadata.storagePath,\n [getField('url')]: metadata.url,\n [getField('moduleId')]: metadata.moduleId,\n [getField('businessId')]: metadata.businessId,\n [getField('uploadedAt')]: metadata.uploadedAt,\n };\n\n // 可选字段\n if (metadata.hash !== undefined) record[getField('hash')] = metadata.hash;\n if (metadata.cdnUrl !== undefined) record[getField('cdnUrl')] = metadata.cdnUrl;\n if (metadata.userId !== undefined) record[getField('userId')] = metadata.userId;\n if (metadata.expiresAt !== undefined) record[getField('expiresAt')] = metadata.expiresAt;\n if (metadata.metadata !== undefined) record[getField('metadata')] = metadata.metadata;\n if (metadata.status !== undefined) record[getField('status')] = metadata.status;\n if (metadata.processingStatus !== undefined) record[getField('processingStatus')] = metadata.processingStatus;\n if (metadata.versions !== undefined) record[getField('versions')] = metadata.versions;\n if (metadata.tags !== undefined) record[getField('tags')] = metadata.tags;\n\n return record;\n };\n\n /**\n * 将数据库记录转换为 FileMetadata\n */\n const toFileMetadata = (record: any): FileMetadata => {\n const metadata: FileMetadata = {\n id: record[getField('id')],\n filename: record[getField('filename')],\n originalName: record[getField('originalName')],\n mimeType: record[getField('mimeType')],\n size: record[getField('size')],\n storageType: record[getField('storageType')],\n storagePath: record[getField('storagePath')],\n url: record[getField('url')],\n moduleId: record[getField('moduleId')],\n businessId: record[getField('businessId')],\n uploadedAt: record[getField('uploadedAt')],\n };\n\n // 可选字段\n if (record[getField('hash')]) metadata.hash = record[getField('hash')];\n if (record[getField('cdnUrl')]) metadata.cdnUrl = record[getField('cdnUrl')];\n if (record[getField('userId')]) metadata.userId = record[getField('userId')];\n if (record[getField('expiresAt')]) metadata.expiresAt = record[getField('expiresAt')];\n if (record[getField('metadata')]) metadata.metadata = record[getField('metadata')];\n if (record[getField('status')]) metadata.status = record[getField('status')];\n if (record[getField('processingStatus')]) metadata.processingStatus = record[getField('processingStatus')];\n if (record[getField('versions')]) metadata.versions = record[getField('versions')];\n if (record[getField('tags')]) metadata.tags = record[getField('tags')];\n\n return metadata;\n };\n\n return {\n async save(metadata: FileMetadata): Promise<void> {\n try {\n const record = toDbRecord(metadata);\n\n // 检查是否存在\n const existing = await db\n .select()\n .from(table)\n .where(eq(table[getField('id')], metadata.id))\n .limit(1);\n\n if (existing && existing.length > 0) {\n // 更新\n await db\n .update(table)\n .set(record)\n .where(eq(table[getField('id')], metadata.id));\n\n logger.info(`✅ [DrizzleRepository] 文件元数据已更新: ${metadata.id}`);\n } else {\n // 插入\n await db.insert(table).values(record);\n logger.info(`✅ [DrizzleRepository] 文件元数据已插入: ${metadata.id}`);\n }\n } catch (error) {\n logger.error(`❌ [DrizzleRepository] 保存失败: ${metadata.id}`, error);\n throw error;\n }\n },\n\n async get(fileId: string): Promise<FileMetadata | null> {\n try {\n const result = await db\n .select()\n .from(table)\n .where(eq(table[getField('id')], fileId))\n .limit(1);\n\n if (!result || result.length === 0) {\n return null;\n }\n\n return toFileMetadata(result[0]);\n } catch (error) {\n logger.error(`❌ [DrizzleRepository] 查询失败: ${fileId}`, error);\n throw error;\n }\n },\n\n async query(options: FileQueryOptions): Promise<PaginatedResult<FileMetadata>> {\n try {\n const {\n page = 1,\n pageSize = 20,\n moduleId,\n businessId,\n userId,\n mimeType,\n status,\n startDate,\n endDate,\n tags,\n } = options;\n\n // 构建查询条件\n const conditions: SQL[] = [];\n\n if (moduleId) {\n conditions.push(eq(table[getField('moduleId')], moduleId));\n }\n if (businessId) {\n conditions.push(eq(table[getField('businessId')], businessId));\n }\n if (userId) {\n conditions.push(eq(table[getField('userId')], userId));\n }\n if (mimeType) {\n conditions.push(eq(table[getField('mimeType')], mimeType));\n }\n if (status) {\n conditions.push(eq(table[getField('status')], status));\n }\n if (startDate) {\n conditions.push(sql`${table[getField('uploadedAt')]} >= ${startDate}`);\n }\n if (endDate) {\n conditions.push(sql`${table[getField('uploadedAt')]} <= ${endDate}`);\n }\n if (tags && tags.length > 0) {\n // 假设 tags 是 JSON 数组字段\n for (const tag of tags) {\n conditions.push(sql`${table[getField('tags')]} @> ${JSON.stringify([tag])}`);\n }\n }\n\n // 查询总数\n const countResult = await db\n .select({ count: sql<number>`count(*)` })\n .from(table)\n .where(conditions.length > 0 ? and(...conditions) : undefined);\n\n const total = Number(countResult[0]?.count || 0);\n\n // 查询数据\n const offset = (page - 1) * pageSize;\n const result = await db\n .select()\n .from(table)\n .where(conditions.length > 0 ? and(...conditions) : undefined)\n .orderBy(desc(table[getField('uploadedAt')]))\n .limit(pageSize)\n .offset(offset);\n\n const items = result.map(toFileMetadata);\n\n return {\n items,\n total,\n page,\n pageSize,\n totalPages: Math.ceil(total / pageSize),\n };\n } catch (error) {\n logger.error(`❌ [DrizzleRepository] 查询列表失败`, error);\n throw error;\n }\n },\n\n async delete(fileId: string): Promise<void> {\n try {\n await db\n .delete(table)\n .where(eq(table[getField('id')], fileId));\n\n logger.info(`🗑️ [DrizzleRepository] 文件元数据已删除: ${fileId}`);\n } catch (error) {\n logger.error(`❌ [DrizzleRepository] 删除失败: ${fileId}`, error);\n throw error;\n }\n },\n\n async batchDelete(fileIds: string[]): Promise<void> {\n try {\n if (fileIds.length === 0) return;\n\n // 批量删除\n await db\n .delete(table)\n .where(sql`${table[getField('id')]} = ANY(${fileIds})`);\n\n logger.info(`🗑️ [DrizzleRepository] 批量删除成功: ${fileIds.length} 个文件`);\n } catch (error) {\n logger.error(`❌ [DrizzleRepository] 批量删除失败`, error);\n throw error;\n }\n },\n };\n}\n\n"]}
|