写在前面
闲来无事,最近使用vue全家桶结合nodejs搭建了一个简单的网站,在前端使用的axios做请求,后端框架使用express框架,在前端做数据请求时,因为axios默认的使用multipart/form-data编码方式进行参数提交,一般默认来说,post请求不涉及到文件上传一般都是使用的x-www-form-urlencoded编码方式进行参数提交,然后...噩梦开始了...
(ps:觉得比较啰嗦的可直接看结论,哈哈^_^)
问题还原
因为axios默认使用multipart/form-data编码方式,因此我们需要在请求头中添加一行代码:
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
此时在服务器端接收参数时,发现使用req.body无法获取参数(默认已经使用中间件解析参数):
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
百度后发现,需要使用qs中间件将axios 请求参数序列化,也就是使用如下代码:
if (config.method === 'post') {
config.data = qs.stringify(config.data)
}
现在服务器端能够正常的接收到数据,并且存入数据库,本以为这样就完了...
(补充一句:如果上传的vey/value,value值不是对象,而是单个的string或者number等,服务器端是可以正常接收到参数,也就是说可以使用req.body.key取到数据的。只有是对象,数组等类型,默认也是字符串,并且key/value都是字符串,因此想使用req.body.key是不行的)
因结构需要,有两个参数需上传对象,并且存入数据库中,首先,前端上传参数如图1所示:
刚开始测试的时候使用的apizza插件进行服务器端调试,发现上传参数没问题(并未做存入数据库处理),后使用前后端联调方式进行,发现前端上传的数据格式如图2所示:
我们可以看到,此时links是单引号,当时并未想到是字符串,因为第一次使用axios,也为后面的踩坑埋下伏笔...
通过观察存入数据库中的数据发现,links字段并未存入数据库,因为前面使用插件调通的,因此并未多想,monoose数据模型如图3所示:
分析原因
开始以为是存入对象需要将模型中的links字段更改为Miexd类型数据,但是发现没用,然后花了两天时间,查各种文档,一直将问题定位在了数据库存储类型上....
结果今天早上起床后继续调试,终于发现哪里不对,图2的links字段,好像有个单引号,突然反应过来,这不就是字符串吗?立马对比插件和axios发出去的请求,发现插件请求可以获取到,而axios请求却获取不到?忽然想起来,前端有一句:
需要使用qs中间件将axios 请求参数序列化
结果看代码是:
qs.stringify(config.data)
这个和
JSON.stringify()
何其相识~~~
与之对应的肯定需要:
qs.parse()
结果在服务器端加入了这样一段代码后:
var req = qs.parse(req.body);
就能正常解析上传的参数。。。自此问题解决。。。。
结论
在使用axios进行请求时候请注意以下几点:
1.axios默认使用的编码方式为:multipart/form-data,如需使用x-www-form-urlencoded编码方式,请使用qs中间件将参数序列化。(如不序列化,服务器端无法获取到上传的参数)
2.服务器端我是采用的nodejs,此时需要将qs序列化后的参数反序列化,将其转化为JSON格式。
后记
俗话说,有得必有失。。。虽然调BUG调的有待难受,但是,收获也很多...
造成这次BUG有多方面原因:
1.自己不熟悉axios框架。
2.较粗心,一直未曾发觉上传的参数是字符串。
3.mongoose使用的不熟悉(一直以为是数据库存储的原因,数据模型建立的有问题。。。)
收获:
1.通过这个BUG,重新翻阅了mongoose的相关操作,对mongoose理解加深。
2.重新翻阅了http相关的知识点,了解简单的http请求头的信息,以及基本原理。
3.重新了解了一遍axios的API请求,进一步熟悉axios的请求。
ps:
以上内容仅为自己的学习过程,欢迎大家取其精华,丢其糟粕。若对以上内容有不同简介或看法,欢迎一起探讨。
企鹅号:1041415167 邮箱地址:zth1041415167@outlook.com