import { $t } from '#/locales'; const OLE2_SIGNATURE = [208, 207, 17, 224, 161, 177, 26, 225]; const supportedExtensions = Object.freeze([ 'txt', 'pdf', 'docx', 'md', 'pptx', 'xlsx', 'csv', ]); const supportedExtensionSet = new Set(supportedExtensions); const supportedTypeLabel = supportedExtensions .map((extension) => extension.toUpperCase()) .join('、'); function extensionOf(fileName: string) { const normalizedName = String(fileName || '') .trim() .toLowerCase(); const dotIndex = normalizedName.lastIndexOf('.'); return dotIndex === -1 ? '' : normalizedName.slice(dotIndex + 1); } function supports(fileName: string) { return supportedExtensionSet.has(extensionOf(fileName)); } async function validateFiles(files: File[]) { for (const file of files) { const extension = extensionOf(file.name); if (!supportedExtensionSet.has(extension)) { throw new Error( $t('message.upload.unsupportedFileType', { fileName: file.name, types: supportedTypeLabel, }), ); } if (extension !== 'xlsx') { continue; } const prefix = new Uint8Array(await file.slice(0, 8).arrayBuffer()); if (hasZipSignature(prefix)) { continue; } const messageKey = startsWith(prefix, OLE2_SIGNATURE) ? 'message.upload.legacyExcelAsXlsx' : 'message.upload.invalidXlsx'; throw new Error($t(messageKey, { fileName: file.name })); } } /** * 知识库导入与工作流文档解析共用的文件格式策略。 */ export const DocumentParseFilePolicy = Object.freeze({ accept: supportedExtensions.map((extension) => `.${extension}`).join(','), supportedExtensions, supportedTypeLabel, supports, validateFiles, }); function hasZipSignature(prefix: Uint8Array) { return ( prefix.length >= 4 && prefix[0] === 80 && prefix[1] === 75 && ((prefix[2] === 3 && prefix[3] === 4) || (prefix[2] === 5 && prefix[3] === 6) || (prefix[2] === 7 && prefix[3] === 8)) ); } function startsWith(prefix: Uint8Array, signature: number[]) { return ( prefix.length >= signature.length && signature.every((value, index) => prefix[index] === value) ); }