【Vue + ElementUI】实现前端调用接口传递 form-data 类型入参及总结遇到的问题记录(状态码 415 问题及记录如何生成 File 文件对象)
(1)实现 Vue 前端组装一个 Form-Data 类型入参并解决 415 状态码问题;(2)解决如何根据文件路径转换成 File 文件对象,再拼接进 Form-Data 入参;(3)使用 ElementUI el-upload 组件,实现手动上传文件,并拼接进 Form-Data 入参。
👉 个人博客主页 👈
📝 一个努力学习的程序猿
其他前端组件使用和踩坑记录文章,欢迎您查看:
先叙述一下开发需求:
有一个入参类型是 Form-Data 的接口,在其他的页面功能点上,配置了一个入参的示例,并入库保存。而在当前的需求中,进入当前这个需求的页面功能点上时,先通过其他接口拿到这个入参示例,然后将它拼装成 Form-Data 类型入参,最后传递给这个支持 Form-Data 类型的接口,成功调用即完成。而在满足以上流程后,还要支持手动上传文件,然后再拼接入参调用接口。
总结一下,即 本文要解决的问题及踩到的坑就是:
(1)如何在前端组装一个 Form-Data 类型入参 及 成功将参数传递给接口(在这个过程中要解决: 415 状态码问题);
(2)因为在本需求中,入参示例其实是已经配置好的,在前端拿到时,其中的文件类型只能也肯定是一个存放在主机指定位置上的路径。因此第二个问题就是:如何将一个文件路径转换成 File 文件对象传递给接口(除此以外,也使用 el-upload 支持手动上传文件,并在文件上传成功后,拼接入参调用接口)。
具体内容将在下文说明。
(在具体说明所有问题前,需要额外说明的是:请先确保各位的接口在使用其他工具调用时,是 100% 能调通的。比如笔者先在 Postman 上进行了测试,发现接口正常,所以就证明文中遇到的所有问题,都是在前端发生的)
Vue:前端组装 form-data 类型入参 踩坑记录
415 状态码问题 及 组装 Form-Data 类型入参
因为是初次接触 在前端组装 Form-Data 类型的入参,所以必不可少的就是在网上查阅资料。但是在网上找到了一些方法后,结果报错,状态码为 415。
通过查阅发现,415 的问题原因是,请求头 header 的 Content-Type 和调用接口传递的入参出现了差异,比如入参是 Form-Data 类型,但是 Content-Type 却是 application/json。
因此,对该问题的解决方案 先看简要代码:
const params = new FormData();
// 做数据处理
for (let i = 0; i < this.params.length; i++) {
params.append(this.params[i].key, this.params[i].value);
}
// 调用接口
check(params).then(res => {
// 其他操作
});
export const check = (query) => {
return request({
url: 'xxx',
method: 'post',
data: query
})
}
总结一下就是:像上面代码一样,使用 new FormData() 创建 FormData 对象,然后用 append 添加参数。而调用的接口,比如在这里的 check 就和普通的接口一样,不需要做特殊处理。
需要特殊说明的,踩到的坑 是:
(1)在碰到 415 的时候,很多网上的文章都说要在接口上手动添加 headers。但笔者测试发现,这样做是行不通的,最后依然会是 415 或者其他奇奇怪怪的问题。如果传递的入参是 JSON 类型还说的过去,但是如果是 Form-Data 类型,且需要上传文件的时候,后面会自动生成一串 boundary,这是手动添加 headers 做不到的。
而实际上,我们根本不需要手动添加 headers,因为 axios 会自动处理设置Content-Type ,不需要手动设置。
(2)因为在这里要传递 Form-Data 类型入参,而很多网上的文章都说要使用 Qs 库。但通过测试发现,这样使用依然会是失败的,不是 415 就是接口提示入参错误。先展示一下使用 Qs 库的效果:
console.log(Qs.stringify({
name: 'test',
url: 'csdn'
}));
当然不排除这样可以成功传递 Form-Data 类型入参的可能性,但既然可以直接使用 new FormData() 操作,那就肯定不需要再额外引入其他库。
而通过以上的用法,显然还没有实现需求。因为在这里还没涉及到上传文件及对文件处理的用法。接下来就是如何将得到的文件地址调整成 File 对象传递给接口。
将文件的主机地址调整成 File 对象
因为在之前的需求中已经提到了,笔者在这里需要考虑将一个存储在主机上指定位置的文件路径,转换成一个 File 对象传递。否则只传递路径肯定会是入参异常的 500 状态码。
而最后找到的解决方法,它的参考到的文章如下:
https://blog.csdn.net/waxuanwa/article/details/125624577
虽然上面原文章中的用法 针对于处理图片,但去掉针对图片的动作即可(传入文件的 url 地址和文件名称):
getFileFromUrl(url, fileName) {
return new Promise((resolve, reject) => {
let blob = null;
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
// 加载时处理
xhr.onload = () => {
// 获取返回结果
blob = xhr.response;
const file = new File([blob], fileName);
// 返回结果
resolve(file);
};
xhr.onerror = (e) => {
reject(e)
};
// 发送
xhr.send();
});
}
最后返回的 File 对象就是这样的效果(和 el-upload 的效果一致,el-upload 的用法在下文说明):
剩下的就是把它拼装进入参,使用 FormData 对象,再将其 append 加入即可(参考上文第一部分,拼装 Form-Data 入参)。
el-upload 上传的文件,用于 Form-Data 类型入参
通过上文已经实现:拼装 Form-Data 类型的入参,在其中如果碰到的文件是一个文件路径,那就将它转换成 File 对象。而如果要手动上传文件,再拼装 Form-Data 类型入参,就可以使用 ElementUI 的 el-upload 组件。
相关 el-upload 的详细使用可以参照我之前的总结文章:
https://blog.csdn.net/qq_45613931/article/details/125258861
在这里简单贴一下核心代码(不能直接使用,请自行调整测试):
<template>
<div>
<el-upload
:on-remove="handleRemove"
:on-error="handleError"
action="#"
:limit="1"
:file-list="showList"
:http-request="httpRequest"
>
<el-button size="small" type="primary">
点击上传
</el-button>
</el-upload>
</div>
</template>
<script>
export default {
data() {
return {
showList: []
};
},
methods: {
// 上传失败
handleError(error) {
this.$message.error('文件上传失败!' + error.message);
},
// 上传文件具体调用
httpRequest(content) {
this.$message.success('文件上传成功');
console.log(content.file);
},
// 5.5 移除文件内容
handleRemove() {
this.showList = [];
}
}
};
</script>
总结来说,只要上传成功,那么在 httpRequest 的输出结果中,就可以直接拿到 File 对象,不需要做任何额外操作。之后只需要 append 进 FormData 对象即可:
更多推荐
所有评论(0)