createUploader
此函数用于文件上传,通过自定义配置创建一个上传器实例,并返回暂停、继续等回调函数
使用方式
js
import { createUploader } from 'file-uploader';
const config = {
....你的配置
}
const { upload, pause, resume, state } = createUploader(config);
参数
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
config | Config | 是 | 上传器配置 |
返回值
参数名 | 类型 | 说明 |
---|---|---|
pause | () => void | 暂停上传 |
resume | () => void | 继续上传 |
upload | () => void | 开始上传 |
state | State | 可用参数 |
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 配置
参数名 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
chunkSize | Number | 否 | 5 * 1024 * 1024 | 单个切片大小(单位:字节),默认 5MB |
concurrency | Number | 否 | 5 | 并发上传数量 |
maxRetries | Number | 否 | 3 | 失败重试次数 |
startOffset | Number | 否 | 0 | 断点续传偏移量(从指定分片开始上传) |
includeChunks | Array<Number> | 否 | - | 指定需要上传的切片索引数组,默认上传所有切片 |
hash | Boolean | 否 | false | 是否计算文件整体哈希值(用于秒传验证) |
threads | number | 否 | 系统CPU核心数 - 2 | 计算 hash 所需要的 webworker 线程数 |
awaitHash | Boolean | 否 | true | 是否等待哈希计算完成(仅当hash:true 时生效),大文件建议设为false |
chunkMap | Boolean | Object | 否 | false | 分片哈希计算配置:true -同步计算{enable:true, async:true} -异步计算 |
uploadFunction | Function | 是 | - | 上传函数,调用接口实现分片上传逻辑 |
customHash | Function | Object | 否 | - | 自定义哈希计算函数或配置对象,用于自定义计算文件哈希值。传入函数时,只在文件上传前调用一次,传入对象且 flow 为 true 时,则开启流式调用,每个分片上传前都会调用 |
onProgress | Function | 否 | - | 上传进度回调,参数为{percent, loaded, total} |
onSpeed | Function | 否 | - | 上传速度回调(单位:KB/s) |
onSuccess | Function | 否 | - | 上传成功回调 |
beginHash | Function | 否 | - | 开始计算哈希时的回调(仅当hash:true 时触发) |
endHash | Function | 否 | - | 哈希计算完成时的回调(仅当hash:true 时触发) |
配置示例
js
// 自定义上传函数
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: { enable: true, async: true }, // 异步计算分片哈希
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;
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;
/**
* 【可选】是否计算文件哈希,默认 false 不计算hash值
* @default false
*/
hash?: boolean;
/**
* 【可选】指定计算hash所需要的webworker线程数
* @default 系统CPU核心数 - 2
*/
threads?: number;
/**
* 可选】自定义计算哈希函数:
* 支持两种模式:
* 1. 直接传入整体文件的哈希函数
* 2. 传入一个对象,启用 流式计算 模式:
* - flow: 是否启用分片流式处理(chunk)模式
* - calculationHash: 分片级哈希函数
*/
customHash?:
| FileHashFn
| {
flow: Boolean;
calculationHash: ChunkHashFn;
};
/**
* 【可选】是否等待哈希计算完成再上传,默认 true
* @default true
*/
awaitHash?: boolean;
/**
* 【可选】是否计算所有切片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;
/**
* 【回调】全部分片上传完成且合并成功时触发
*/
onSuccess?: () => 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 属性
属性名 | 类型 | 说明 |
---|---|---|
progress | number | 上传进度百分比 (0-100) |
speed | string | 实时上传速度(带单位),例如 "1.23 MB/s" |
uploadEnd | boolean | 是否已完成上传 |
hash | string | 文件哈希值(基于分片内容的 SHA256 计算) |
file | File | null | 当前上传的原始 File 对象 |
totalChunks | number | 总分片数(包含断点续传的偏移量分片) |
errorMsg | Error | null | 上传错误信息(失败时不为 null) |
allChunks | [] | 所有切片数组(存储分片数据) |
hashMap | Map<number, string> | 分片哈希映射表 (需开启计算才会生成,默认关闭) |
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>;
}