# AF-LFUpload **Repository Path**: wzfdhr/af-lfupload ## Basic Information - **Project Name**: AF-LFUpload - **Description**: # AF-LFUpload 前端大文件上传组件(React + TypeScript)。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-04 - **Last Updated**: 2026-01-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: React ## README # AF-LFUpload 前端大文件上传组件(React + TypeScript)。特性: ## 作为 npm 组件库使用 - 安装:`npm i af-lfupload` - 使用: ```tsx import { LargeFileUploader, createMockProtocol } from 'af-lfupload' const protocol = createMockProtocol() export function Demo() { return } ``` > 注意:`react` / `react-dom` 是 peerDependencies,需要由业务项目自行安装。 ## 开发 - 安装依赖:`npm i` - 启动:`npm run dev` - 构建(库):`npm run build` - 构建(Demo):`npm run build:demo` - 代码检查:`npm run lint` ## 组件:LargeFileUploader 入口: - 组件:[src/components/LargeFileUploader/LargeFileUploader.tsx](src/components/LargeFileUploader/LargeFileUploader.tsx) - 导出:[src/components/LargeFileUploader/index.ts](src/components/LargeFileUploader/index.ts) ### Props - `protocol: UploadProtocol`:上传协议实现(必填) - `multiple?: boolean`:是否允许选择多个文件(默认 `true`) - `accept?: string`:原生 input accept - `disabled?: boolean` - `maxFiles?: number`:最多允许添加多少个文件 - `maxFileSizeBytes?: number`:单文件最大字节数(超出会被过滤) 上传行为: - `chunkSizeBytes?: number`:切片大小(默认 5MB) - `concurrency?: number`:并发上传分片数(默认 3) - `maxRetries?: number`:单分片最大重试次数(默认 3) - `retryDelayMs?: (attempt:number)=>number`:重试延迟策略(默认指数退避) - `autoStart?: boolean`:添加文件后是否自动开始上传(默认 `false`) - `persist?: boolean`:是否启用断点续传持久化(默认 `true`) 事件回调: - `onChange?: (items: UploadFileItem[]) => void` - `onFileAdded?: (item: UploadFileItem) => void` - `onFileRemoved?: (item: UploadFileItem) => void` - `onStatusChange?: (item: UploadFileItem) => void` - `onProgress?: (item: UploadFileItem) => void` - `onSuccess?: (item: UploadFileItem) => void` - `onError?: (item: UploadFileItem) => void` 自定义渲染: - `renderItem?: ({ item, actions }) => ReactNode` - `actions.start()` / `actions.pause()` / `actions.cancel()` / `actions.remove()` ### 状态模型(UploadFileItem) 类型定义见:[src/uploader/types.ts](src/uploader/types.ts) - `status`:`idle | queued | fingerprinting | uploading | paused | completed | error | canceled` - `progress`:`totalBytes / uploadedBytes / percent / speedBps?` - `fileId?`:断点续传指纹(异步计算,完成后写入) ## 统一协议:UploadProtocol 接口定义: - [src/uploader/types.ts](src/uploader/types.ts) 核心方法: - `id: string`:协议唯一 id(用于持久化命名空间) - `init(req)`:创建/恢复一次上传会话,返回 `{ uploadId, uploadedParts? }` - `uploadPart(req)`:上传单个分片(1-based partNumber) - `complete(req)`:提交合并 - `abort(req)`:取消会话 - `getUploadedParts?(req)`:可选;从服务端查询已上传分片(更强的断点续传保证) 已提供实现: - Mock(纯前端演示):[src/uploader/protocols/mockProtocol.ts](src/uploader/protocols/mockProtocol.ts) - HTTP(fetch 版协议示例):[src/uploader/protocols/httpProtocol.ts](src/uploader/protocols/httpProtocol.ts) ## 断点续传设计(当前实现) - 文件指纹:`fingerprintFile(file)` 使用 metadata + 头/尾片段 SHA-256,避免读取全文件 - 本地持久化:localStorage 记录 `protocolId + fileId -> { uploadId, chunkSizeBytes, partCount, uploadedParts }` - 恢复流程: - 若存在本地 session 且切片参数一致:继续未上传分片 - 若协议支持 `getUploadedParts`:优先与服务端对齐(更可靠) ## Demo 默认页面已替换为 Demo: - [src/App.tsx](src/App.tsx) 使用 `createMockProtocol()` 可以在没有后端时演示并发、失败重试、断点续传。 # React + TypeScript + Vite This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. Currently, two official plugins are available: - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh ## React Compiler The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). ## Expanding the ESLint configuration If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: ```js export default defineConfig([ globalIgnores(['dist']), { files: ['**/*.{ts,tsx}'], extends: [ // Other configs... // Remove tseslint.configs.recommended and replace with this tseslint.configs.recommendedTypeChecked, // Alternatively, use this for stricter rules tseslint.configs.strictTypeChecked, // Optionally, add this for stylistic rules tseslint.configs.stylisticTypeChecked, // Other configs... ], languageOptions: { parserOptions: { project: ['./tsconfig.node.json', './tsconfig.app.json'], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, ]) ``` You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: ```js // eslint.config.js import reactX from 'eslint-plugin-react-x' import reactDom from 'eslint-plugin-react-dom' export default defineConfig([ globalIgnores(['dist']), { files: ['**/*.{ts,tsx}'], extends: [ // Other configs... // Enable lint rules for React reactX.configs['recommended-typescript'], // Enable lint rules for React DOM reactDom.configs.recommended, ], languageOptions: { parserOptions: { project: ['./tsconfig.node.json', './tsconfig.app.json'], tsconfigRootDir: import.meta.dirname, }, // other options... }, }, ]) ```