miniprogram-file-uploader

小程序大文件上传库。

小程序中的上传文件 wx.uploadFile 接口有大小限制(10M),采用分块上传的方式进行解决。该上传库依赖 FileSystemManager.readFile 接口进行文件的分块读取,基础库版本 2.10.0 及以上支持,可通过 isSupport 接口判断。

支持的特性

  • [x] 分块读取,可限制占用内存大小
  • [x] 分块并发上传
  • [x] 支持暂停、恢复、取消、重传
  • [x] 支持秒传,计算md5判断服务端是否已存在
  • [x] 支持进度、预估剩余时间、平均速度、出错自动重试
  • [x] 错误处理

安装

通过 npm 安装

npm i miniprogram-file-uploader

使用

创建一个 uploader 实例:


if (Uploader.isSupport()) {
  const uploader = new Uploader({
    tempFilePath,
    totalSize: size,
    uploadUrl: UPLOAD_URL,
    mergeUrl: MERGE_URL,
  })

  uploader.upload()
}

实例化后可以选择监听一些事件:

// 成功或失败都会触发
uploader.on('complete', (res) => {
  console.log('upload complete', res)
})

// 文件上传成功
uploader.on('success', (res) => {
  console.log('upload success', res)
})

// 文件上传失败
uploader.on('fail', (res) => {
  console.log('fail', res)
})

// 文件进度变化
uploader.on('progress', (res) => {
  this.setData({
    progress: res.progress,
    uploadedSize: parseInt(res.uploadedSize / 1024),
    averageSpeed: parseInt(res.averageSpeed / 1000),
    timeRemaining: res.timeRemaining
  })
})

服务端如何接收

由于小程序端采用分块上传,服务端也需要进行秒传验证、接收分块、分块合并等处理,可参考 example/server/app.js 的实现,共涉及到三个接口:

  1. 秒传验证 (verifyUrl: Get)

当配置项 testChunkstrue 时,小程序端会预先发送一个验证请求,利用 spark-md5 根据文件内容计算出唯一标识,服务端可根据该值判断是否已经上传,或者上传了部分分片,并返回给前端。小程序端依此可以实现续传或秒传的效果。需注意的是,计算文件的 hash 值也有一定的时间和内存损耗。

请求参数

属性 类型 说明
identifier String 文件的 md5 值
fileName String 文件名

返回参数

属性 类型 说明
url String 已上传时返回线上文件路径
needUpload Boolean 是否需要上传
uploadedChunks Array<Number> 未完全上传时,返回已上传的分块序号
  1. 接收分块 (uploadUrl: Post)

小程序端采用 wx.request 接口发送文件的二进制数据,content-typeapplication/octet-stream,服务端接收后放入暂存区,收到合并请求后进行合并。

上传接口的 query 中包含如下分块信息:

  • identifier:文件的唯一标识
  • index:分块的序号,从 0 开始
  • chunkSize: 分块大小,最后一块可能小于该值
  • fileName:文件名,传入的文件名
  • totalChunks:分块的总数量,依据 chunkSize 计算
  • totalSize:文件总大小
  1. 合并分块 (mergeUrl: Get)

分块全部发送后,小程序端发送合并请求,服务端按分片序号进行合并,返回最终的文件线上路径。

请求参数

属性 类型 说明
identifier String 文件的 md5 值
fileName String 文件名

返回参数

属性 类型 说明
url String 线上文件路径

对于每个请求,小程序端依据配置 successStatusfailStatus 和返回的 statusCode 判断成功或失败。

  • 200, 201, 202: 请求成功
  • 404, 415, 500, 501: 请求失败,会终止文件上传
  • 其他状态码: 出错了,但是会自动重试

API 文档

Uploader

配置项

实例化的时候可以传入配置项:

const uploader = new Uploader(option)
配置项 必填 类型 说明
tempFilePath String 小程序内的文件临时路径
totalSize Number 文件的总大小,单位 B
verifyUrl String 秒传验证接口
uploadUrl String 接收分块接口
mergeUrl String 合并分块接口
maxConcurrency Number 并发上传数,默认 5,最大不超过 10
generateIdentifier Function 可覆盖默认的生成文件唯一标识的函数,需返回 identifier
chunkSize Number 分块大小,默认 5 * 1024 * 1204 B
maxMemory Number 加载文件最大占用的内存,默认 100 * 1024 * 1024 B,内存占用过大时可能导致小程序闪退
query Object 上传分块时可添加自定义的参数
header Object 上传分块时可添加自定义的请求头
testChunks Boolean 是否需要进行秒传验证,默认为 false
maxChunkRetries Number 请求失败时最大重试次数,默认为 0
chunkRetryInterval Number 自动重试间隔,默认为 0
timeout Number 请求超时时间,默认 10000 ms
successStatus Array 认为响应式成功的响应码,默认 [200, 201, 202]
failStatus Array 认为是出错的响应码,默认 [404, 415, 500, 501]
verbose Boolean 是否输出开始日志,默认 false

方法

  • .on(event, callback) 监听事件
  • .off(event, callback) 移除事件监听
  • .upload() 开始上传
  • .pause() 暂停上传
  • .resume() 继续上传,与 pause 配对使用
  • .cancel() 取消所有上传文件,与 upload 配对使用
  • .isSupport() 当前小程序版本是否支持

事件

通过 on 方法进行监听

  • success,上传成功时触发,e = {errCode: 0, url: 'xxx'}
  • fail,上传失败时触发,e = {errCode: 0, errMsg: 'xxx'}
  • complete,上传成功或失败时触发,返回值同 successfail
  • retry,请求重传时触发,e = {statusCode: 302, url: 'xxx'}
  • progess,上传进度变化时触发,返回内容如下:
属性 类型 说明
totalSize Number 文件的总大小,单位 B
progress Number 上传进度,范围 [0, 100]
uploadedSize Number 已上传大小,单位 B
averageSpeed Number 平均速度,单位 B/s
timeRemaining Number 预估剩余时间,单位 ms

注意事项

  1. 由于 wx.requst 没有 progressUpdate 事件,这里的 progress 事件在收到分块请求结果后触发;
  2. 真机 chooseVideo 返回的临时文件,每次计算 md5 值不同,无法使用秒传功能;
  3. 真机缺少 console.timeEnd 方法,部分开发日志会打印不出来;