阅读 295

koa-bodyparser 不支持解析 FormData

其实我觉得解决了,就不算是坑,至少对于我自己来说,所以记录下来,也算帮助看到这篇博客的有缘的朋友们。当然不想看“废话”的朋友们,可以看标题,以及结尾就行,自己再实践一下,效果一样。

1. 起因

我正在折腾自己的一个小 demo。我给它预定的一个功能是能够实现用户自主上传头像,当然我不大想自己从零实现该功能,在前端我用到了 Ant Design 的 Upload 组件。并且我希望在上传头像的时候,将前端 store 里面的用户名传递过去,为了在数据库中存储嘛!这样也好办,因为人性的 Upload 的提供了传递额外参数的属性 data。而在服务端,使用了 koa-multer 来存储图片。

在最开始,我的服务端代码使用的是我那一点蹩脚的 Node.js 写的,当然也用到了 Express 框架。血的教训告诉我们不要对自己太自信,我连脚手架都没有使用,所有的代码都挤在一个 index.js 文件里面,很多重复的代码,真的,一团糟。受够了这些肮脏的代码后,我决定痛改前非,进修了一下 Node.js。最终决定使用 Koa 重构服务端的代码,当然这次用到了脚手架,让代码结构分工更加清晰,然后问题就产生了。

2. 问题描述及解析

2.1 描述

看过 Ant Design 组件文档的小伙伴肯定知道,Upload 组件传递数据是使用的 post 方法。我们也应该知道 Express 做了一些封装,我们可以在 res.body 中拿到 post 请求的数据,在 res.query 中拿到 get 请求的数据。

同样在 koa 中,因为对响应和请求做了一些封装,我们可以在 ctx.request.body 中拿到 post 请求的数据,在 ctx.request.query 中拿到 get 请求的数据。But,这一次,Koa 没能接收到我 Upload 组件传递的数据

我打开 Google 开发者工具的网络面板一看,网络请求把数据传递过去了呀!那就是我服务端的代码有问题。

image-20211020205434463.png

于是我开始在服务端排查错误,发现逻辑没啥问题,但就是接收不到,这时候上边截图里面的 FormData 就引起了我的怀疑,我隐隐约约记得一般 post 请求里面的数据,不是放在这个里面的,我用 axios 发送了一次 post 请求试了一下,果然

image-20211020205938895.png

2.2 解析

发现问题了,我就开始找资料啊,发现这其中好像还是有点东西的。大家应该知道,一次 Http 请求可以分为下面几个部分:请求行,请求头,空行,请求体。不论是 FormData 还是 Request Payload 都是在请求体中。而且请求的数据具体是在哪个里面,还和 Content-Type 有关。这是我在网上找到的原话,引用一下

  1. 如果是 application/x-www-form-urlencoded的话,则为Form Data方式

  2. 如果是application/jsonmultipart/form-data的话,则为 RequestPayload 的方式。

我也验证了一下,使用 form 表单 Post 请求时,是下面截图这样的,而这次请求的 Content-Type 也刚好为 application/x-www-form-urlencoded

    <form action="/abc" method="POST">
        <input name="name" type="text">
        <input name="password" type="text">
        <button>提交</button>
    </form>复制代码

image-20211020213440849.png

其实悄咪咪说一下,我发现开发者工具显示 form 表单的 get 请求,数据是放在 Query String Parameters 中,搞不太清,get 请求不就放在 URL 上嘛。

3. 解决

上边说了一大堆,终于可以解决了。我们都说 Koa 相对于 Express 来说更加轻量,因为内部没有封装那么多的中间件啥的,问题的根源和解决方案就都是中间件了 ,在我们用 Koa 的脚手架 koa-generator 创建的项目中,默认是使用 koa-bodyparser 这个中间件来解析请求体的,但是这个中间件不支持 FormData,我们换一个中间件,用 koa-body 就行,它支持 FormData 的解析。

const koaBody = require('koa-body')({
  multipart: true,  // 允许上传多个文件
});
app.use(koaBody)复制代码

4. 意外

偶,我的女娲娘娘,你永远知道,惊喜和意外总是意外先来临。 因为使用了 koa-body 的缘故,我突然不能在 ctx.req.file 里面获取 koa-multer 存储图片的相对路径了。好吧代码再次发生改变,因为我看到了网络上有 koa2 使用 koa-body 代替 koa-bodyparserkoa- 和 koa-multer 的博客,所以放弃了使用 koa-multer 。但我没有按照这上边来,因为我只是需要一个相对路径,好存储,所以关于配置,我是这样写的

const koaBody = require('koa-body');

app.use(koaBody({
  multipart:true,
  encoding:'gzip',
  formidable:{
    uploadDir:path.join(__dirname,'public/uploads/'+new Date().getFullYear() + (new Date().getMonth()+1) + new Date().getDate()),//存储路径
    keepExtensions: true,//保持文件的后缀
    maxFieldsSize:2 * 1024 * 1024,
    onFileBegin:(name,file) => {
      //我要新增一个属性,给这个属性相对地址的值,因为绝对地址还要我解析
      const index = file.path.search(/public/i)
      file.newPath = file.path.slice(index).replace(/\/g, "/")
    },
    onError:(err)=>{
      console.log(err);
    }
  }
}));


作者:小林呼叫呐鲁铎
链接:https://juejin.cn/post/7022876982270492703


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐