Skip to content

createMultiUploader

此函数用于多文件批量上传,通过自定义配置创建一个多文件上传器实例,支持并发控制、秒传、断点续传等功能。 多文件上传演示地址:http://jiang-12-13.com:7988/

使用方式

js
import { createMultiUploader } from 'enlarge-file-upload';

const multiUploader = createMultiUploader({
    uploadFunction: async ({ chunk, index, hash, cancelToken }) => {
        // 你的分片上传逻辑
    },
    // ... 其他配置
});

// 添加文件
multiUploader.addFiles(files);

参数

参数名类型必填说明
configMultiUploadConfig多文件上传器配置

返回值

方法名类型说明
addFiles(files) => string[]添加文件到队列,返回文件ID
start() => void手动开始上传
pauseAll() => void暂停所有正在上传的文件
resumeAll() => void恢复所有已暂停的文件
pauseUpload(fileId) => void暂停指定文件
resumeUpload(fileId) => void恢复指定文件
removeFile(fileId) => void移除指定文件
retryFile(fileId) => void重试失败的文件
cancelAll() => void取消所有上传
clear() => void清空已完成/失败的文件
getStats() => Stats获取统计信息
getFileList() => FileItem[]获取文件列表

ts 类型

ts
interface MultiUploader {
  /** 添加文件到上传队列 */
  addFiles: (files: File | File[]) => string[];
  /** 手动开始上传(当 autoStart: false 时使用) */
  start: () => void;
  /** 暂停所有正在上传的文件 */
  pauseAll: () => void;
  /** 恢复所有已暂停的文件 */
  resumeAll: () => void;
  /** 暂停指定文件的上传 */
  pauseUpload: (fileId: string) => void;
  /** 恢复指定文件的上传 */
  resumeUpload: (fileId: string) => void;
  /** 移除指定文件 */
  removeFile: (fileId: string) => void;
  /** 重试失败的文件 */
  retryFile: (fileId: string) => void;
  /** 取消所有上传 */
  cancelAll: () => void;
  /** 清空已完成/失败的文件 */
  clear: () => void;
  /** 获取统计信息 */
  getStats: () => MultiUploadStats;
  /** 获取文件列表 */
  getFileList: () => MultiUploadFileItem[];
}

Config 配置

此处仅列举部分参数,详细参数请查看 createUploader

参数名类型必填默认值说明
maxConcurrentFilesnumber1最大并发文件数(1=顺序上传)
autoStartbooleantrue添加文件后是否自动开始上传

配置示例

js
const multiUploader = createMultiUploader({
    // ========== 基础配置 ==========
    chunkSize: 5 * 1024 * 1024,     // 5MB 分片
    /**
     * 最大并发文件数(1=顺序上传)
     * @description 假设用户选择了5个文件上传,此时,默认值为1,代表顺序上传
     * 如果 `maxConcurrentFiles` 设置为 2,那么会同时上传 2 个文件
     * @default 1
     */
    maxConcurrentFiles: 2, 
    concurrency: 5,                 // 每个文件 5 个分片并发
    maxRetries: 3,                  // 失败重试 3 次
    autoStart: true,                // 自动开始上传
    
    // ========== 分片上传函数(必需)==========
    uploadFunction: async ({ chunk, index, hash, cancelToken }) => {
        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('index', index);
        formData.append('hash', hash);
        
        await axios.post('/api/upload', formData, { cancelToken });
    },
    
    // ========== 回调函数 ==========
    onFileAdded: (fileItem) => {
        // 大文件使用更大的分片和更高并发
        if (fileItem.file.size > 500 * 1024 * 1024) {
            return {
                chunkSize: 10 * 1024 * 1024, // 10MB
                concurrency: 5,
                hash: false, // 跳过 hash 计算
            };
        }
        return {};
    },
    onBeforeUpload: async (fileItem) => {
        // 秒传检测
        const res = await axios.post('/api/check', { hash: fileItem.hash });
        if (res.data.exists) {
            return { skip: true };  // 跳过上传
        }
        // 断点续传
        if (res.data.uploadedChunks) {
            return { includeChunks: res.data.needChunks };
        }
        return {};
    },
    
    onFileProgress: (fileItem, progress) => {
        console.log(`${fileItem.file.name}: ${progress}%`);
    },
    
    onFileSuccess: (fileItem) => {
        console.log(`上传成功: ${fileItem.file.name}`);
    },
    
    onAllSuccess: () => {
        console.log('全部上传完成');
    },
});

ts 类型

ts
interface MultiUploadConfig {
  /** 
   * @description 其余部分参数请参考createUploader ts类型Config相关属性 
  **/

  /** 【可选】最大并发文件数,默认 1(顺序上传) */
  maxConcurrentFiles?: number;
  /** 【可选】添加文件后自动开始上传,默认 true */
  autoStart?: boolean;
  
  // ========== 回调函数 ==========
  /** 文件添加时触发(hash 计算之前),可设置单文件配置用来覆盖全局配置*/
  onFileAdded?: (fileItem: MultiUploadFileItem) => Config | void;
  /** 上传前钩子,可用于秒传/断点续传 */
  onBeforeUpload?: (fileItem: FileItem) => Promise<BeforeUploadResult | void>;
  /** 文件状态变化回调 */
  onFileStatusChange?: (fileItem: FileItem, status: string) => void;
  /** 文件进度变化回调 */
  onFileProgress?: (fileItem: FileItem, progress: number) => void;
  /** 哈希计算进度回调 */
  onHashProgress?: (fileItem: FileItem, percentage: number) => void;
  /** 文件上传速度回调 */
  onFileSpeed?: (fileItem: FileItem, speed: string) => void;
  /** 文件剩余时间回调 */
  onFileEta?: (fileItem: FileItem, eta: number) => void;
  /** 文件开始上传回调 */
  onFileStart?: (fileItem: FileItem) => void;
  /** 文件上传成功回调 */
  onFileSuccess?: (fileItem: FileItem) => void;
  /** 文件上传失败回调 */
  onFileError?: (fileItem: FileItem, error: Error) => void;
  /** 文件被取消/移除回调 */
  onFileCancelled?: (fileItem: FileItem) => void;
  /** 全局进度回调 */
  onGlobalProgress?: (info: GlobalProgressInfo) => void;
  /** 所有文件上传成功回调 */
  onAllSuccess?: () => void;
}

interface BeforeUploadResult {
  /** 设为 true 跳过实际上传(秒传) */
  skip?: boolean;
  /** 断点续传:需要上传的分片索引数组 */
  includeChunks?: number[];
  /** 断点续传:起始分片偏移量 */
  startOffset?: number;
}

interface GlobalProgressInfo {
  /** 总进度百分比 (0-100) */
  percent: number;
  /** 已上传总字节数 */
  totalUploadedSize: number;
  /** 总字节数 */
  totalSize: number;
  /** 预估剩余时间(秒) */
  eta: number;
}

interface UploadOptions {
  /** 当前分片数据 */
  chunk: Blob;
  /** 当前分片索引(从 0 开始) */
  index: number;
  /** 文件哈希值 */
  hash: string;
  /** axios 取消令牌 */
  cancelToken: CancelToken;
}

FileItem 文件对象

每个文件在队列中以 FileItem 对象表示,包含以下属性:

属性名类型说明
idstring唯一标识符(自动生成)
fileFile原始文件对象
statusstring状态:pending | calculating_hash | uploading | paused | success | error
progressnumber上传进度(0-100)
hashProgressnumber哈希计算进度(0-100)
hashstring | null文件哈希值(计算完成后填充)
totalChunksnumber总分片数(由库自动计算)
speedstring | null上传速度字符串,如 "2.50 MB/s"
speedBytesPerSecnumber上传速度(字节/秒)
etanumber预估剩余时间(秒)
errorMsgstring | Error | null错误信息(失败时填充)

ts 类型

ts
interface MultiUploadFileItem {
  /** 唯一标识符 */
  id: string;
  /** 原始文件对象 */
  file: File;
  /** 文件状态 */
  status: 'pending' | 'calculating_hash' | 'uploading' | 'paused' | 'success' | 'error';
  /** 上传进度 (0-100) */
  progress: number;
  /** 哈希计算进度 (0-100) */
  hashProgress: number;
  /** 文件哈希值 */
  hash: string | null;
  /** 总分片数 */
  totalChunks: number;
  /** 上传速度字符串 */
  speed?: string | null;
  /** 上传速度 (字节/秒) */
  speedBytesPerSec?: number;
  /** 预估剩余时间 (秒) */
  eta?: number;
  /** 错误信息 */
  errorMsg?: string | Error | null;
}

Stats 统计信息

调用 getStats() 返回的统计对象:

属性名类型说明
totalnumber总文件数
pendingnumber等待中的文件数
calculatingnumber正在计算哈希的文件
uploadingnumber正在上传的文件数
pausednumber已暂停的文件数
successnumber上传成功的文件数
errornumber上传失败的文件数
activeCountnumber当前占用的并发槽位
queueLengthnumber队列中等待的文件数

ts 类型

ts
interface MultiUploadStats {
  total: number;
  pending: number;
  calculating: number;
  uploading: number;
  paused: number;
  success: number;
  error: number;
  activeCount: number;
  queueLength: number;
}