简介
小程序官方提供的api wx.uploadFile一次只能上传一个文件,一般的解决方案是调用多次,但是存在最大并发限制10,wx-multipart实现了一般的content-type 为 multipart/form-data的post请求。
原理
对于post请求,小程序官方提供了wx.request和wx.uploadFile。但是wx.uploadFile一次只能上传一个文件,那可不可以利用wx.request呢?Yes
根据官方文档data可以为ArrayBuffer类型,那么只需要解决两个问题。
1. 设置content-type为multipart/form-data;
wx.request({
url,
data: buffer,
header: {
'content-type': `multipart/form-data; boundary=${Boundary}`
},
method: 'post'
})
2. 将字符串和文件转化为ArrayBuffer
首先看下multipart/form-data的数据格式 rfc7578
------WebKitFormBoundarycf2702ca043fdf6c4fd42
Content-Disposition: form-data; name="number"
13812345678
------WebKitFormBoundarycf2702ca043fdf6c4fd42
Content-Disposition: form-data; name="image"; filename="1.png"
Content-Type: image/png
imageFileData
------WebKitFormBoundarycf2702ca043fdf6c4fd42--
数据body被Boundary分隔成几部分,Boundary的值为content-type里的boundary。
每部分包含Content-Disposition,name,filename,换行符\r\n,Content-Type和内容
最后以’–’+Boundary+’–'结尾
了解了body格式后,很容易根据field的name和value生成相应字符串
字符串转化为ArrayBuffer
由于js字符串编码格式是utf-16,需要先转化为utf-8,再转化为ArrayBuffer
let strToBuf = function(utf16Str) {
let utf8Arr = []
let byteSize = 0
for (let i = 0; i < utf16Str.length; i++) {
let code = utf16Str.charCodeAt(i)
if (code >= 0x00 && code <= 0x7f) {
byteSize += 1
utf8Arr.push(code)
} else if (code >= 0x80 && code <= 0x7ff) {
byteSize += 2
utf8Arr.push(192 | (31 & (code >> 6)))
utf8Arr.push(128 | (63 & code))
} else if (
(code >= 0x800 && code <= 0xd7ff) ||
(code >= 0xe000 && code <= 0xffff)
) {
byteSize += 3
utf8Arr.push(224 | (15 & (code >> 12)))
utf8Arr.push(128 | (63 & (code >> 6)))
utf8Arr.push(128 | (63 & code))
} else if (code >= 0x10000 && code <= 0x10ffff) {
byteSize += 4
utf8Arr.push(240 | (7 & (code >> 18)))
utf8Arr.push(128 | (63 & (code >> 12)))
utf8Arr.push(128 | (63 & (code >> 6)))
utf8Arr.push(128 | (63 & code))
}
}
let arrayBuf = new ArrayBuffer(utf8Arr.length)
let buf = new Uint8Array(arrayBuf)
for (let i = 0; i < utf8Arr.length; i++) {
buf[i] = utf8Arr[i]
}
return buf
}
读取文件内容
对于文件内容,小程序官方提供了FileSystemManager.readFile()方法
FileSystemManager.readFile({
filePath,//要读取的文件的路径 如果不传 encoding,则以 ArrayBuffer 格式读取文件的二进制内容
success(res){
}
})
文件content-type
对于文件的content-type 利用库mime-types根据文件名获取
总结
wx-multipart 欢迎star