From e99c72f02a2f6f25464d7c4cc4ce3e33bb25fc81 Mon Sep 17 00:00:00 2001 From: gaoziman <2942894660@qq.com> Date: Sat, 20 Dec 2025 12:12:54 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=B1=BB=E5=9E=8B):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E7=B1=BB=E5=9E=8B=E5=AE=9A?= =?UTF-8?q?=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 定义 FileType 类型支持多种文件格式(图片、PDF、文档、代码等) - 实现 UploadFile 接口包含完整的文件上传状态管理 - 添加 FileUploadConfig 配置接口和默认配置 - 提供 MIME 类型与文件类型映射 - 实现文件大小格式化和验证工具函数 --- src/types/file-upload.ts | 173 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/types/file-upload.ts diff --git a/src/types/file-upload.ts b/src/types/file-upload.ts new file mode 100644 index 0000000..a40d786 --- /dev/null +++ b/src/types/file-upload.ts @@ -0,0 +1,173 @@ +/** + * 文件上传相关类型定义 + */ + +// 支持的文件类型 +export type FileType = + | 'image' // 图片:jpg, png, gif, webp + | 'pdf' // PDF 文档 + | 'document' // Word 文档 + | 'spreadsheet'// Excel 表格 + | 'code' // 代码文件 + | 'text' // 纯文本 + | 'markdown' // Markdown 文件 + | 'archive' // 压缩包 + | 'unknown'; // 未知类型 + +// 上传文件信息 +export interface UploadFile { + id: string; + file: File; + name: string; + size: number; + type: FileType; + mimeType: string; + previewUrl?: string; // 图片预览URL(仅图片类型) + uploadProgress: number; // 上传进度 0-100 + status: 'pending' | 'uploading' | 'success' | 'error'; + error?: string; // 错误信息 + uploadedUrl?: string; // 上传成功后的URL +} + +// 文件上传配置 +export interface FileUploadConfig { + maxFileSize: number; // 最大文件大小(字节) + maxFiles: number; // 最大文件数量 + allowedTypes: FileType[]; // 允许的文件类型 + allowedMimeTypes: string[];// 允许的 MIME 类型 +} + +// 默认配置 +export const DEFAULT_UPLOAD_CONFIG: FileUploadConfig = { + maxFileSize: 20 * 1024 * 1024, // 20MB + maxFiles: 10, + allowedTypes: ['image', 'pdf', 'document', 'spreadsheet', 'code', 'text', 'markdown'], + allowedMimeTypes: [ + // 图片 + 'image/jpeg', + 'image/png', + 'image/gif', + 'image/webp', + 'image/svg+xml', + // PDF + 'application/pdf', + // Word + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + // Excel + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + // 文本 + 'text/plain', + 'text/markdown', + 'text/csv', + // 代码 + 'text/javascript', + 'text/typescript', + 'text/html', + 'text/css', + 'application/json', + 'application/xml', + ], +}; + +// 文件类型映射 +export const MIME_TO_FILE_TYPE: Record = { + 'image/jpeg': 'image', + 'image/png': 'image', + 'image/gif': 'image', + 'image/webp': 'image', + 'image/svg+xml': 'image', + 'application/pdf': 'pdf', + 'application/msword': 'document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'document', + 'application/vnd.ms-excel': 'spreadsheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'spreadsheet', + 'text/plain': 'text', + 'text/markdown': 'markdown', + 'text/csv': 'spreadsheet', + 'text/javascript': 'code', + 'text/typescript': 'code', + 'text/html': 'code', + 'text/css': 'code', + 'application/json': 'code', + 'application/xml': 'code', + 'application/zip': 'archive', + 'application/x-rar-compressed': 'archive', + 'application/x-7z-compressed': 'archive', +}; + +// 根据 MIME 类型获取文件类型 +export function getFileTypeFromMime(mimeType: string): FileType { + return MIME_TO_FILE_TYPE[mimeType] || 'unknown'; +} + +// 根据文件扩展名获取文件类型 +export function getFileTypeFromExtension(filename: string): FileType { + const ext = filename.split('.').pop()?.toLowerCase() || ''; + + const extensionMap: Record = { + // 图片 + jpg: 'image', jpeg: 'image', png: 'image', gif: 'image', webp: 'image', svg: 'image', + // PDF + pdf: 'pdf', + // 文档 + doc: 'document', docx: 'document', + // 表格 + xls: 'spreadsheet', xlsx: 'spreadsheet', csv: 'spreadsheet', + // 文本 + txt: 'text', + // Markdown + md: 'markdown', markdown: 'markdown', + // 代码 + js: 'code', ts: 'code', jsx: 'code', tsx: 'code', + py: 'code', java: 'code', c: 'code', cpp: 'code', h: 'code', + go: 'code', rs: 'code', rb: 'code', php: 'code', + html: 'code', css: 'code', scss: 'code', less: 'code', + json: 'code', xml: 'code', yaml: 'code', yml: 'code', + sql: 'code', sh: 'code', bash: 'code', + // 压缩包 + zip: 'archive', rar: 'archive', '7z': 'archive', tar: 'archive', gz: 'archive', + }; + + return extensionMap[ext] || 'unknown'; +} + +// 格式化文件大小 +export function formatFileSize(bytes: number): string { + if (bytes === 0) return '0 B'; + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; +} + +// 验证文件 +export interface FileValidationResult { + valid: boolean; + error?: string; +} + +export function validateFile( + file: File, + config: FileUploadConfig = DEFAULT_UPLOAD_CONFIG +): FileValidationResult { + // 检查文件大小 + if (file.size > config.maxFileSize) { + return { + valid: false, + error: `文件大小超过限制(最大 ${formatFileSize(config.maxFileSize)})`, + }; + } + + // 检查 MIME 类型 + const fileType = getFileTypeFromMime(file.type) || getFileTypeFromExtension(file.name); + if (!config.allowedTypes.includes(fileType) && fileType !== 'unknown') { + return { + valid: false, + error: `不支持的文件类型:${file.type}`, + }; + } + + return { valid: true }; +}