社区里有不少关于wx.request发送multipart/form-data请求的问题,我看了几个,基本都说wx.request不支持,得用wx.uploadFile来“曲线救国”。我花了些时间研究了一下,找到了如下方法,分享出来,希望能帮助到有需要的人。
首先,服务端,我用的是async-busboy来解析multipart/form-data请求,测试代码直接使用它提供的就可以:https://github.com/m4nuC/async-busboy/blob/master/examples/index.js
小程序端:
如果wx.request中仅指定'content-type'为'multipart/form-data',服务端会报"no multipart boundary was found"的错误,就像这个帖子里描述的:https://developers.weixin.qq.com/community/develop/doc/000e64476f8d80fd7b9765d5655c00
尽管指定了content-type为'mutipart/form-data',但是wx.request并不会为我们自动添加boundary,既然如此,我们自己加不就可以了吗?经过测试,确认了这个方法可行,前端示例代码如下:
wx.request({ url: 'http://localhost:8080/test/multipart-form' , method: 'POST' , header: { 'content-type' : 'multipart/form-data; boundary=XXX' }, data: '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="field1"' + '\r\n' + '\r\nvalue1' + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="field2"' + '\r\n' + '\r\nvalue2' + '\r\n--XXX--' }) |
这里,我向服务端传递了两个参数:field1=value1, field2=value2,服务端得到的结果如下:
如果对multipart/form-data的请求体格式不了解,可以参考这篇文章:https://ec.haxx.se/http-multipart.html
wx.request中的data结构看起来有些复杂,有需要的可以封装一下,封装好的API欢迎跟帖分享出来。
https://github.com/zlyboy/wx-formdata
感谢分享。 的确也是遇到服务端这边只能接受 formdata的请求,按照这种拼写,已经实现了。
的确如博主所说,wx.request中的data结构太复杂,因此对此进行了封装。贴出封装发来。
formdata (obj = {}) { let result = '' for (let name of Object.keys(obj)) { let value = obj[name]; result += '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="'+name+'”'+ '\r\n' + '\r\n' + value } return result+'\r\n--XXX--' }
把formdata中的参数名和值封装为一个 obj对象。 此方法拼写出来的字符串,跟手工拼写的完全一样,但提交到服务器却显示错误提示。
博主有时间也看一下这个方法。
下面是直接拼写的,可以提交成功。
data:'\r\n--XXX' + '\r\nContent-Disposition: form-data; name="sn"' + '\r\n' + '\r\n' + this.data.formData.sn + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="devicetype"' + '\r\n' + '\r\n' + this.data.formData.devicetype + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="param1"' + '\r\n' + '\r\n' + this.data.formData.param1 + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="param2"' + '\r\n' + '\r\n' + this.data.formData.param2 + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="param3"' + '\r\n' + '\r\n' + this.data.formData.param3 + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="param4"' + '\r\n' + '\r\n' + this.data.formData.param4 + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="param5"' + '\r\n' + '\r\n' + this.data.formData.param5 + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="resultjson"' + '\r\n' + '\r\n' + resultjson + '\r\n--XXX--' ,
我去看一下服务端怎么接收的。
找到问题了!fordata的方法中的双引号之前需要加\转义,否则,就会出错。
这是修改后能正确运行的方法!
formdata (obj = {}) {
let result = ''
for (let name of Object.keys(obj)) {
let value = obj[name];
result +=
'\r\n--XXX' +
'\r\nContent-Disposition: form-data; name=\"'+ name +'\"'+
'\r\n' +
'\r\n' + value
}
return result + '\r\n--XXX--'
},
"content-type":"application/x-www-form-urlencoded"这么设置貌似也可以传递,我用这种方法成功了,可能是我们后台逻辑不一样吧
可以直接传整个对象吗
header: { 'Content-Type': 'multipart/form-data; boundary=XXX' }, data: '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="receive"' + '\r\n' + '\r\n' + '2606290@qq.com' + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="msg"' + '\r\n' + '\r\n' + '4546456456654' + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="subject"' + '\r\n' + '\r\n' + '676756756' + '\r\n--XXX' + '\r\nContent-Disposition: form-data; name="file"; filename="file.pdf"' + '\r\nContent-Type: text/plain' + '\r\n' + '\r\n' + fil + '\r\n--XXX--',
这样是成功时,但是文件流上传到后端,后端转发到邮箱,邮箱打开,文档空白
求大佬贴个完整的代码段,我这个小白折腾了一天都不行...
function fromData(obj) { let fromStr = (k, v) => { let retStr = '' retStr += `\r\n--XXX` retStr += `\r\nContent-Disposition: form-data; name="${k}"` retStr += `\r\n` retStr += `\r\n${v}` return retStr } let valueStr = (any) => { if (typeof any === typeof '') { return any } else { return JSON.stringify(any) } } let retData = '' Object.keys(obj).forEach(k => { retData += fromStr(k, valueStr(obj[k])) }) return retData + `\r\n--XXX--` } // obj = {a: {a: {a:b}}} // fromData(obj)
我这边也是传给服务端的value是字符,应该怎么解决啊
博主 我试用了你的封装方法 但是 传递给后端的value是字符 如何修改呢 我这边想实现调用一次接口 上传多张图片
传文件的格式是不一样的,我没测试,你参考下面这篇文章构造下body试一下,理论上是可行的:
http://chxo.com/be2/20050724_93bf.html