评论

使用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欢迎跟帖分享出来。

点赞 11
收藏
评论

8 个评论

  • 来吧伙计
    来吧伙计
    2020-12-07

    https://github.com/zlyboy/wx-formdata

    2020-12-07
    赞同 11
    回复 9
    • Why not?
      Why not?
      2020-12-08
      挺好的,可以单独写篇文章,介绍介绍,赚点积分,顺道大家还能过去给你提提新需求
      2020-12-08
      回复
    • Allin
      Allin
      2021-03-15
      很棒棒
      2021-03-15
      1
      回复
    • Rick
      Rick
      2021-07-27
      可以,刚好解决了我的问题,谢谢!
      2021-07-27
      回复
    • Nefelibata
      Nefelibata
      2023-02-13
      大佬,请问我用这个封装的formdata传数据后端报错说当前的不是一个multipart请求
      2023-02-13
      回复
    • 蓝强
      蓝强
      2023-06-29
      formData.getData()返回的数据,ArrayBuffer是一个空对象,以前都可以的,不知道是什么原因
      2023-06-29
      回复
    查看更多(4)
  • 辉哥
    辉哥
    2020-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--'
    	,
    





    2020-03-29
    赞同 4
    回复 6
    • Why not?
      Why not?
      2020-03-29
      我试了你的方法,没问题。{field1: 'value1', field2: 'value2'}
      2020-03-29
      1
      回复
    • 辉哥
      辉哥
      2020-03-29回复Why not?
      嗯,那可能是服务端处理上的问题。
      我去看一下服务端怎么接收的。
      2020-03-29
      回复
    • 辉哥
      辉哥
      2020-03-29
      2020-03-29
      4
      回复
    • 彦斌
      彦斌
      2020-06-19
      如果是图片字段你怎么设置?
      2020-06-19
      1
      回复
    • Mr、王
      Mr、王
      2020-11-04回复辉哥
      这这这。。。明明是中文冒号的原因,大哥,让我一顿好找
      2020-11-04
      1
      回复
    查看更多(1)
  • 刘高艺
    刘高艺
    2020-08-31

    "content-type":"application/x-www-form-urlencoded"这么设置貌似也可以传递,我用这种方法成功了,可能是我们后台逻辑不一样吧

    2020-08-31
    赞同 10
    回复 6
    • Lion-July
      Lion-July
      2021-08-05
      这个方法可以,不用组装参数
      2021-08-05
      回复
    • 文文呐_zx🎈
      文文呐_zx🎈
      2023-07-24
      可以,我用了
      2023-07-24
      回复
    • 繁@
      繁@
      2023-10-17
      感谢大哥!!!!
      2023-10-17
      回复
    • 🦁
      🦁
      2023-11-19
      牛批,最佳方法
      2023-11-19
      回复
    • zhi.
      zhi.
      03-20
      你是我的神!!!!!
      03-20
      回复
    查看更多(1)
  • 南佳
    南佳
    2021-06-10
    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--',
    

    这样是成功时,但是文件流上传到后端,后端转发到邮箱,邮箱打开,文档空白

    2021-06-10
    赞同
    回复 3
    • Why not?
      Why not?
      2021-06-11
      那你后端写到文件里也是空白么?
      2021-06-11
      回复
    • 南佳
      南佳
      2021-07-09回复Why not?
      请问图片中的content是什么格式,我想上传pdf,但是不知道怎么传
      2021-07-09
      回复
    • Why not?
      Why not?
      2021-07-11回复南佳
      可以参考参考这个:https://github.com/form-data/form-data
      2021-07-11
      回复
  • 知足。
    知足。
    2020-12-30

    求大佬贴个完整的代码段,我这个小白折腾了一天都不行...

    2020-12-30
    赞同
    回复 1
    • Why not?
      Why not?
      2020-12-30
      上面@子山 写的库可以看看
      2020-12-30
      回复
  • SmilE
    SmilE
    2020-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)
    
    2020-06-30
    赞同
    回复
  • Licy
    Licy
    2020-04-14

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


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

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

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