前言
这是一篇关于微信小程序中文件批量上传的开发实践总结。文件上传听起来很不起眼,即使加上批量二字似乎也不是难事,但是这条平凡之路,铺在微信小程序上似乎变的有些陡峭。
启动
微信还是很 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 连一个文件都传不上去。
郁闷,无奈,为什么会这样,是微信忘了,还是有其他原因限制。(内部人士看到此处,希望能给出合理解释。)
曙光
发扬快狗技术不放弃,不言败的精神,继续上下求索。
既然有防火墙,我们只能搭梯子越过!
思路
- 首先将文件转化成可以解码的格式。
- 将多个编码的字符串一起封装上传。
- 服务端按照约定的编码格式进行解码写入硬盘。
源码
文件编码
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)
})
复制代码
完整代码
后记
这可能是众多方法中最不起眼的一个。
欢迎读者发表更多更优的方法。