Skip to content

createUploader

此函数用于文件上传,通过自定义配置创建一个上传器实例,并返回暂停、继续等回调函数

使用方式

js
import { createUploader } from 'enlarge-file-upload';
const config = {
    ....你的配置
    }
 const { upload, pause, resume, state } = createUploader(config);

参数

参数名类型必填说明
configConfig上传器配置

返回值

参数名类型说明
pause() => void暂停上传
resume() => void继续上传
upload() => void开始上传
stateState可用参数

ts 类型

ts
interface Uploader {
  /**
   * 启动文件上传
   * @param file - 要上传的浏览器 File 对象
   * @throws 分片初始化失败/上传过程中出现未处理错误
   */
  upload: (file: File) => Promise<void>;
  /**
   * 暂停上传(会取消正在传输的请求)
   */
  pause: () => void;
  /**
   * 恢复暂停的上传(从断点继续)
   * @throws 未初始化分片时调用会报错
   */
  resume: () => Promise<void>;
  /**
   * 重置所有状态到初始值(相当于重新初始化)
   * - 清理所有分片数据
   * - 取消所有进行中的请求
   * - 清理定时器和缓存数据
   * - 重置进度到 0%
   */
  reset: () => void;
  /**
   * 实时状态对象,可通过监听相关属性实现响应式更新
   */
  state: State;
}

Config 配置

createMultiUploader的相关配置参数请一并参考此处说明

参数名类型必填默认值说明支持版本
uploadFunctionFunction-上传函数,调用接口实现分片上传逻辑-
chunkSizeNumber5 * 1024 * 1024单个切片大小(单位:字节),默认 5MB-
concurrencyNumber5并发上传数量-
maxRetriesNumber3失败重试次数-
startOffsetNumber0断点续传偏移量(从指定分片开始上传)-
enableLoggingBooleanfalse是否开启日志记录,开启后会在控制台输出上传过程中的日志信息2.4.2
logLevel'DEBUG' | 'INFO' | 'WARN' | 'ERROR''INFO'日志级别,控制输出的最低日志级别,如参数为INFO,则仅输出INFOWARNERROR级别的日志;如参数为DEBUG,则输出所有级别的日志。2.4.2
consoleOutputBooleantrue是否将日志输出到控制台,默认开启。如设置为false,则日志将仅通过 onLog 回调函数输出。2.4.2
onLog(log: Log) => void-自定义日志回调函数,用于接收上传过程中的日志信息。参数 log 包含日志级别、消息内容和元数据。2.4.2
includeChunksArray<Number>-指定需要上传的切片索引数组,默认上传所有切片-
hashBooleantrue是否计算文件整体哈希值-
threadsnumber系统CPU核心数 - 2计算 hash 所需要的 webworker 线程数-
axiosInstanceAxiosInstance-自定义 axios 实例,用于上传文件时的 HTTP 请求。一般不需要使用该属性,只有当提示axios获取为空或者需要自己接管axios时才使用2.4.0
customHashApi
hashMode
'crypto' | 'sha256''crypto'自定义哈希计算 API,默认使用 Web Crypto API,也可以选择使用 sha256 算法2.4.0
awaitHashBooleantrue是否等待哈希计算完成(仅当hash:true时生效),大文件建议设为false-
chunkMapBoolean | Objectfalse分片哈希计算配置:
true-同步计算所有分片hash
{indices:[], async:true}-async为true开启异步计算,indices为需要计算的分片索引数组,默认计算所有分片
-
customHashFunction | Object-自定义哈希计算函数或配置对象,用于自定义计算文件哈希值。传入函数时,只在文件上传前调用一次,传入对象且 flow 为 true 时,则开启流式调用,每个分片上传前都会调用-
onProgressFunction-上传进度回调,参数为{percent, loaded, total}-
onSpeedFunction-上传速度回调(单位:KB/s)-
onSuccessFunction-上传成功回调-
onErrorFunction-上传失败回调-
beginHashFunction-开始计算哈希时的回调(仅当hash:true时触发)-
endHashFunction-哈希计算完成时的回调(仅当hash:true时触发)-
onEtaFunction-上传剩余时间回调2.4.3

配置示例

js
// 自定义上传函数
/**
 * 分片上传处理函数系统入参解释
 * @param {Object} options - 系统入参
 * @param {Blob} options.chunk - 当前分片的二进制数据
 * @param {number} options.index - 当前分片的索引
 * @param {string} options.hash - 当前文件的哈希值(是当前文件hash,不是当前分片)
 * @param {CancelToken} options.cancelToken - 取消令牌(用于取消上传)
 */
async function uploadFunction({ chunk, index, hash, cancelToken }) {
  const formData = new FormData();
  formData.append("chunk", chunk);
  formData.append("hash", hash);
  formData.append("index", index);
  await axios.post("http://xxxx/api/upload", formData, {
    cancelToken,
  });
}
const config = {
  chunkSize: 5 * 1024 * 1024, // 5MB分片
  concurrency: 3, // 并发数3
  maxRetries: 2, // 失败重试2次
  hash: true, // 开启文件哈希计算
  awaitHash: false, // 不等待哈希计算(大文件优化)
  chunkMap: true, // 计算分片hash值
  // axiosInstance: axios, // 你的axios实例。该属性只有在极少数情况下才会使用
  enableLogging: true,  // 开启日志记录
  logLevel: 'INFO', // 日志级别,控制输出的最低日志级别
  onLog: (log) => {
    // 打印日志到控制台 (或者你可以发送到你的服务端)
    console.log(`[${log.level}] ${log.message}`, log.metadata);
  }
  uploadFunction,
  onProgress: (progress) => {
    console.log(`进度: ${progress.percent}%`);
  },
};

ts 类型

ts
/**
 * 自定义哈希计算的返回结果:
 * - hash: 当前文件整体hash值(字符串)
 * - hashMap: 一个 Map,用于存储每个分片的哈希值
 */
type HashResult = Promise<{
  hash: string;
  hashMap: Map<number, string>;
}>;

/**
 * 流式计算模式:
 * - 参数:
 *   - chunk: 当前分片的二进制数据
 *   - index: 当前分片的索引
 * - 返回:
 *   - 一个 Promise,解析为 HashResult
 */
type ChunkHashFn = (chunk: Blob, index: number) => HashResult;

/**
 * 单次计算模式:
 * - 参数:
 *   - file: 完整文件对象
 * - 返回:
 *   - 一个 Promise,解析为 HashResult
 */
type FileHashFn = (file: File) => HashResult;

/**
 * 日志条目接口
 */
export interface LogEntry {
  /**
   * 日志时间戳 (ISO 8601格式)
   */
  timestamp: string;
  /**
   * 会话ID,用于关联同一次上传的所有日志
   */
  sessionId: string;
  /**
   * 日志级别
   */
  level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
  /**
   * 日志消息
   */
  message: string;
  /**
   * 日志元数据
   */
  metadata?: Record<string, any>;
}

export interface Config {
  /**
   * 【必需】分片上传处理函数
   * @example ({ chunk, index, hash }) => axios.post(uploadUrl, formData)
   */
  uploadFunction: (options: UploadOptions) => Promise<void>;
  /**
   * 【可选】分片大小(字节),默认为 5MB
   * @default 5 * 1024 * 1024
   */
  chunkSize?: number;
  /**
   * 【可选】起始分片位置索引(用于断点续传),默认从第一个分片开始
   * @example 3 (从第4个分片开始)
   */
  startOffset?: number;
  /**
   * 【可选】指定要上传的分片索引数组(优先级高于 startOffset)
   * @example [0,2,3] (仅上传索引为0、2、3的分片)
   */
  includeChunks?: number[];
  /**
   * 【可选】上传失败时的最大重试次数,默认 3 次
   * @default 3
   */
  maxRetries?: number;
  /**
   * 【可选】最大并发请求数,默认 5
   * @default 5
   */
  concurrency?: number;
  /**
   * 【可选】是否计算文件哈希,默认 true 计算hash值
   * @default true
   */
  hash?: boolean;
  /**
   * 【可选】指定计算hash所需要的webworker线程数
   * @default 系统CPU核心数 - 2
   */
  threads?: number;
  /**
   * 【可选】自定义 axios 实例,用于上传文件时的 HTTP 请求
   */
  axiosInstance?: AxiosInstance;
  /**
   * 【可选】是否等待哈希计算完成再上传,默认 true
   * @default true
   */
  awaitHash?: boolean;
  /**
   * 【可选】哈希计算模式,默认自动选择
   * - 'crypto': 使用 Web Crypto API(性能更好,但大文件可能内存不足)
   * - 'sha256': 使用自定义 sha256 实现(更稳定,支持超大文件)
   * @default 自动选择:1GB以下文件使用 crypto,1GB以上使用 sha256
   */
  hashMode?: "crypto" | "sha256";
  /**
   * @deprecated 请使用 hashMode 代替,此属性将在未来版本移除
   */
  customHashApi?: "crypto" | "sha256";
  /**
   * 可选】自定义计算哈希函数:
   * 支持两种模式:
   * 1. 直接传入整体文件的哈希函数
   * 2. 传入一个对象,启用 流式计算 模式:
   *    - flow: 是否启用分片流式处理(chunk)模式
   *    - calculationHash: 分片级哈希函数
   */
  customHash?:
  | FileHashFn
  | {
    flow: Boolean;
    calculationHash: ChunkHashFn;
  };
  /**
   * 【可选】是否计算所有切片hash,默认 false
   * @default false
   */
  chunkMap?: boolean | { async: boolean; indices?: number[] };
  /**
   * 【回调】开始计算哈希时触发
   */
  beginHash?: () => void;
  /**
   * 【回调】哈希计算完成后触发,返回最终哈希值
   */
  endHash?: (hash: string) => void;
  /**
   * 【回调】上传进度变化时触发,返回 0-100 的数值
   */
  onProgress?: (progress: number) => void;
  /**
   * 【回调】实时上传速度变化时触发,返回带有单位的字符串
   * @example "2.45 MB/s"
   */
  onSpeed?: (speed: string) => void;
  /**
   * 【回调】预估剩余时间变化时触发,返回剩余秒数
   * @example 120 (表示还剩约2分钟)
   */
  onEta?: (eta: number) => void;
  /**
   * 【回调】全部分片上传完成且合并成功时触发
   */
  onSuccess?: () => void;
  /**
   * 【回调】上传失败时触发,返回错误信息
   */
  onError?: (error: any) => void;
  /**
   * 【可选】是否启用日志记录功能
   * @default false
   */
  enableLogging?: boolean;
  /**
   * 【可选】日志级别,控制输出的最低日志级别
   * @default 'INFO'
   */
  logLevel?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
  /**
   * 【可选】是否将日志输出到浏览器控制台
   * @default true
   */
  consoleOutput?: boolean;
  /**
   * 【回调】日志记录时触发,可用于自定义日志处理(如发送到服务端)
   * @example (log) => { console.log(log); sendToServer(log); }
   */
  onLog?: (log: LogEntry) => void;
}

interface UploadOptions {
  /**
   * 当前分片数据
   * @example new Blob([file.slice(0, chunkSize)])
   */
  chunk: Blob;
  /**
   * 当前分片索引(从0开始计数的绝对位置,包含起始偏移量)
   * @example 如果设定 startOffset=3,则实际索引范围是 [3,4,5...]
   */
  index: number;
  /**
   * 文件的唯一哈希值
   * @example "sha256-xxxxxx"
   */
  hash: string | null;
  /**
   * 用于取消请求的 axios 取消令牌
   * @example axios.CancelToken.source().token
   */
  cancelToken: CancelToken;
}

State 属性

属性名类型说明
progressnumber上传进度百分比 (0-100)
speedstring实时上传速度(带单位),例如 "1.23 MB/s"
uploadEndboolean是否已完成上传
hashstring文件哈希值(基于分片内容的 SHA256 计算)
fileFile | null当前上传的原始 File 对象
totalChunksnumber总分片数(包含断点续传的偏移量分片)
errorMsgError | null上传错误信息(失败时不为 null)
allChunks[]所有切片数组(存储分片数据)
hashMapMap<number, string>分片哈希映射表
(需开启计算才会生成,默认关闭)
etanumber上传剩余时间

ts 类型

ts
interface State {
  /**
   * 上传进度百分比 (0-100)
   */
  progress: number;
  /**
   * 当前实时上传速度(包含单位)
   * @example "1.23 MB/s"
   */
  speed: string;
  /**
   * 是否已完成上传
   */
  uploadEnd: boolean;
  /**
   * 文件哈希值(基于分片内容的 SHA256)
   */
  hash: string;
  /**
   * 当前上传的原始 File 对象
   */
  file: File | null;
  /**
   * 总分片数(包含偏移量分片)
   */
  totalChunks: number;
  /**
   * 上传错误信息
   */
  errorMsg: Error | null;
  /**
   * 所有切片
   */
  allChunks: [];
  /**
   * 所有切片hashMap(需要开启计算才有,默认不开启)
   */
  hashMap: Map<number, string>;
  /**
   * 上传剩余时间
   */
  eta: number;
}