评论

使用wx.request发送multipart/form-data请求的方法

使用wx.request发送multipart/form-data请求的方法

社区里有不少关于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欢迎跟帖分享出来。

点赞 3
收藏
评论

4 个评论

  • 辉哥
    辉哥
    03-29

    感谢分享。 的确也是遇到服务端这边只能接受 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--'
    	,
    





    03-29
    赞同 1
    回复 4
    • Why not?
      Why not?
      03-29
      我试了你的方法,没问题。{field1: 'value1', field2: 'value2'}
      03-29
      1
      回复
    • 辉哥
      辉哥
      03-29回复Why not?
      嗯,那可能是服务端处理上的问题。
      我去看一下服务端怎么接收的。
      03-29
      回复
    • 辉哥
      辉哥
      03-29
      03-29
      3
      回复
    • 彦斌
      彦斌
      06-19
      如果是图片字段你怎么设置?
      06-19
      回复
  • SmilE
    SmilE
    06-30
    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)
    
    06-30
    赞同
    回复
  • Licy
    Licy
    04-14

    我这边也是传给服务端的value是字符,应该怎么解决啊


    04-14
    赞同
    回复 6
    • Why not?
      Why not?
      04-15
      那你实际传的是什么?文件?
      04-15
      回复
    • Licy
      Licy
      04-15回复Why not?
      对,图片文件,然后按照上面的方法比葫芦画瓢抄下来之后,发现传到服务端的是图片文件变成了字符串
      04-15
      回复
    • Licy
      Licy
      04-15回复Why not?
      然后昨天我就还是用那个uploadFile来做的
      04-15
      回复
    • Why not?
      Why not?
      04-15
      图片有图片的格式,我上面的例子是传普通的字符串。不是不得已的话,其实不建议用这种方法的,uploadFile好用就用uploadFile
      04-15
      回复
    • Licy
      Licy
      04-15回复Why not?
      嗯嗯,好的,谢谢大佬了
      04-15
      回复
    查看更多(1)
  • 奔奔
    奔奔
    2019-12-26

    博主 我试用了你的封装方法 但是 传递给后端的value是字符 如何修改呢 我这边想实现调用一次接口 上传多张图片

    2019-12-26
    赞同
    回复 6
    • Why not?
      Why not?
      2019-12-26
      2019-12-26
      回复
    • 辉哥
      辉哥
      03-29
      图片的例子还传文本原理一样。仔细一点拼写就好。
      03-29
      回复
    • 朱志新
      朱志新
      04-09
      我试了传图片一次只传了20个字节,
      04-09
      回复
    • Licy
      Licy
      04-14
      我这边也是传给服务端的value是字符,你的解决了吗
      04-14
      回复
    • 刘聪
      刘聪
      07-14
      多张图片上传解决了吗
      07-14
      回复
    查看更多(1)
登录 后发表内容