miniprogram-file-uploader

小程序大文件上传库。

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

支持的特性

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

安装

通过 npm 安装

  1. npm i miniprogram-file-uploader

使用

创建一个 uploader 实例:

  1. if (Uploader.isSupport()) {
  2. const uploader = new Uploader({
  3. tempFilePath,
  4. totalSize: size,
  5. uploadUrl: UPLOAD_URL,
  6. mergeUrl: MERGE_URL,
  7. })
  8. uploader.upload()
  9. }

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

  1. // 成功或失败都会触发
  2. uploader.on('complete', (res) => {
  3. console.log('upload complete', res)
  4. })
  5. // 文件上传成功
  6. uploader.on('success', (res) => {
  7. console.log('upload success', res)
  8. })
  9. // 文件上传失败
  10. uploader.on('fail', (res) => {
  11. console.log('fail', res)
  12. })
  13. // 文件进度变化
  14. uploader.on('progress', (res) => {
  15. this.setData({
  16. progress: res.progress,
  17. uploadedSize: parseInt(res.uploadedSize / 1024),
  18. averageSpeed: parseInt(res.averageSpeed / 1000),
  19. timeRemaining: res.timeRemaining
  20. })
  21. })

服务端如何接收

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

  1. 秒传验证 (verifyUrl: Get)

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

请求参数

属性类型说明
identifierString文件的 md5 值
fileNameString文件名

返回参数

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

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

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

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

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

请求参数

属性类型说明
identifierString文件的 md5 值
fileNameString文件名

返回参数

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

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

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

API 文档

Uploader

配置项

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

  1. const uploader = new Uploader(option)
配置项必填类型说明
tempFilePathString小程序内的文件临时路径
totalSizeNumber文件的总大小,单位 B
verifyUrlString秒传验证接口
uploadUrlString接收分块接口
mergeUrlString合并分块接口
maxConcurrencyNumber并发上传数,默认 5,最大不超过 10
generateIdentifierFunction可覆盖默认的生成文件唯一标识的函数,需返回 identifier
chunkSizeNumber分块大小,默认 5 1024 1204 B
maxMemoryNumber加载文件最大占用的内存,默认 100 1024 1024 B,内存占用过大时可能导致小程序闪退
queryObject上传分块时可添加自定义的参数
headerObject上传分块时可添加自定义的请求头
testChunksBoolean是否需要进行秒传验证,默认为 false
maxChunkRetriesNumber请求失败时最大重试次数,默认为 0
chunkRetryIntervalNumber自动重试间隔,默认为 0
timeoutNumber请求超时时间,默认 10000 ms
successStatusArray认为响应式成功的响应码,默认 [200, 201, 202]
failStatusArray认为是出错的响应码,默认 [404, 415, 500, 501]
verboseBoolean是否输出开始日志,默认 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,上传进度变化时触发,返回内容如下:
属性类型说明
totalSizeNumber文件的总大小,单位 B
progressNumber上传进度,范围 [0, 100]
uploadedSizeNumber已上传大小,单位 B
averageSpeedNumber平均速度,单位 B/s
timeRemainingNumber预估剩余时间,单位 ms

注意事项

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