af-lfupload
v0.0.1
Published
前端大文件上传组件(React + TypeScript)。特性:
Readme
AF-LFUpload
前端大文件上传组件(React + TypeScript)。特性:
作为 npm 组件库使用
- 安装:
npm i af-lfupload - 使用:
import { LargeFileUploader, createMockProtocol } from 'af-lfupload'
const protocol = createMockProtocol()
export function Demo() {
return <LargeFileUploader protocol={protocol} />
}注意:
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/index.ts
Props
protocol: UploadProtocol:上传协议实现(必填)multiple?: boolean:是否允许选择多个文件(默认true)accept?: string:原生 input acceptdisabled?: booleanmaxFiles?: 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[]) => voidonFileAdded?: (item: UploadFileItem) => voidonFileRemoved?: (item: UploadFileItem) => voidonStatusChange?: (item: UploadFileItem) => voidonProgress?: (item: UploadFileItem) => voidonSuccess?: (item: UploadFileItem) => voidonError?: (item: UploadFileItem) => void
自定义渲染:
renderItem?: ({ item, actions }) => ReactNodeactions.start()/actions.pause()/actions.cancel()/actions.remove()
状态模型(UploadFileItem)
类型定义见:src/uploader/types.ts
status:idle | queued | fingerprinting | uploading | paused | completed | error | canceledprogress:totalBytes / uploadedBytes / percent / speedBps?fileId?:断点续传指纹(异步计算,完成后写入)
统一协议:UploadProtocol
接口定义:
核心方法:
id: string:协议唯一 id(用于持久化命名空间)init(req):创建/恢复一次上传会话,返回{ uploadId, uploadedParts? }uploadPart(req):上传单个分片(1-based partNumber)complete(req):提交合并abort(req):取消会话getUploadedParts?(req):可选;从服务端查询已上传分片(更强的断点续传保证)
已提供实现:
- Mock(纯前端演示):src/uploader/protocols/mockProtocol.ts
- HTTP(fetch 版协议示例):src/uploader/protocols/httpProtocol.ts
断点续传设计(当前实现)
- 文件指纹:
fingerprintFile(file)使用 metadata + 头/尾片段 SHA-256,避免读取全文件 - 本地持久化:localStorage 记录
protocolId + fileId -> { uploadId, chunkSizeBytes, partCount, uploadedParts } - 恢复流程:
- 若存在本地 session 且切片参数一致:继续未上传分片
- 若协议支持
getUploadedParts:优先与服务端对齐(更可靠)
Demo
默认页面已替换为 Demo:
使用 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 uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC 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.
Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
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 and eslint-plugin-react-dom for React-specific lint rules:
// 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...
},
},
])