阅读 3413

【实践总结】挣脱枷锁实现批量上传

前言

这是一篇关于微信小程序中文件批量上传的开发实践总结。文件上传听起来很不起眼,即使加上批量二字似乎也不是难事,但是这条平凡之路,铺在微信小程序上似乎变的有些陡峭。

启动

微信还是很 nice ,提供了一些和网络相关的方法。其中 wx.uploadFile 用于将本地资源上传到服务器。

// 微信官方例子

wx.chooseImage({
  success (res) {
    const tempFilePaths = res.tempFilePaths
    wx.uploadFile({
      url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
      filePath: tempFilePaths[0],
      name: 'file',
      formData: {
        'user': 'test'
      },
      success (res){
        const data = res.data
        //do something
      }
    })
  }
})

复制代码
  • 属性 filePath 类型 String 作用将上传文件的临时路径或者网络路径。 不是 Array 类型显然无法同时上传多个。(遗憾)
  • 属性 formData 类型 Object ,作用HTTP 请求中其他额外的 formdata (注意:小程序中无法使用 new FormData)

于是乎:

是否可以将文件路径封装成 Object 作为 formData 的参数实现批量上传呢?

结果同样是遗憾的,我们在服务端只会接收到一堆临时文件地址的字符串。(尴尬)

为什么 filePath 的参数就可以而 formdata 就不行?

原因:微信内部会将 filePath 临时文件地址转化成实际的二进制文件流传到服务端,但是在 formData 中并不会如此处理只是当做特定数据类型处理上传。

探索

抱着试试看的心理,又看了一下 wx.request 方法,读过无数遍后,依旧是绝望,似乎还不如 wx.uploadFile 连一个文件都传不上去。

郁闷,无奈,为什么会这样,是微信忘了,还是有其他原因限制。(内部人士看到此处,希望能给出合理解释。)

曙光

发扬快狗技术不放弃,不言败的精神,继续上下求索。

既然有防火墙,我们只能搭梯子越过!

思路

  1. 首先将文件转化成可以解码的格式。
  2. 将多个编码的字符串一起封装上传。
  3. 服务端按照约定的编码格式进行解码写入硬盘。

源码

文件编码

const fileSystemManager = wx.getFileSystemManager()

fileSystemManager.readFile({
        filePath: filePath, // 例如图片临时路径
        encoding: 'base64',
        success (res) {
          let { data } = res // 编码后的数据
        }
      })

复制代码

数据封装

let fileList = [data1, data2, data3]

复制代码

上传

wx.request({
  url: 'kuaigou/fe/api', 
  data: {
    fileList: fileList
  },
  header: {
    'content-type': 'application/json' // 默认值
  },
  success (res) {
    console.log(res.data)
  }
})

复制代码

服务端(nodeJs)

let decodeImg = Buffer.from(data, 'base64') // data 为编码的数据

  fs.writeFile('path', decodeImg, 'base64').then((data => {
      console.log('data:suc', data)
    
    })).catch(err => {
      console.error('data:err', err)
    })

复制代码

完整代码

github

后记

这可能是众多方法中最不起眼的一个。

欢迎读者发表更多更优的方法。

关注我们

关注公众号前端论道