前言
在搭建网站时,上传文件都是一个不可避免的需求。为了实现上传文件功能,需要使用<input type="file"/>
、formData数据和ajax(axios)来实现。
实现选取本地文件
实现文件上传功能的第一步就是要实现选取本地文件功能。通过<input type="file"/>
就可以实现选取本地文件功能。
<body>
<input id="file type="file" />
</body>
页面效果:
可以看到,上面的页面效果并不是很好看。然而,当你想着着手去改动该input标签样式时,你会发现非常的难以实现所要的效果。对此,一般的做法就是,新建一个button,通过button的click事件去触发<input type="file"/>
的click事件。
数据封装
通过<input type="file"/>
控件,我们可以获取到所要上传的文件。但是要将其传给后端我们还需将文件数据进行封装。这一步要就要借助FormData了。做法如下:
/*
* 当input的值发生改变时触发
**/
changeFile() {
const file = document.querySelector("#file").files[0]; // 获取需要上传的文件数据
if (file) {
let fd = new FormData();
fd.append("file", file);
}
},
使用 axios 上传文件
/*
* 使用 axios的post方法上传文件
**/
upload(formdata) {
let that = this;
that.axios
.post("/file/upload", formdata)
.then(res => {
})
.catch(err => {
});
},
以上就是上传文件前端的全部代码了。但是有几点需要注意的:
注意事项:
1. 同时上传其他数据
有时候,我们上传数据是不单单需要文件数据,还需要一些额外的数据(如:用户名等)。这是我们就不能像以往的post用法那样直接在添加参数到请求body里了。因为在body里添加而外参数,会导致后端无法获取解析文件数据(具体原因请看第二项注意事项)。正常做法是把额外的数据也添加到FormData里面。代码如下:
/*
* 当input的值发生改变时触发
**/
changeFile(name) {
const file = document.querySelector("#file").files[0]; // 获取需要上传的文件数据
if (file) {
let fd = new FormData();
fd.append("file", file);
fd.append("name", name); // 用户名
}
},
2.切忌设置Content-Type
向后端传输FormData数据,Content-Type 的类型一定得是 multipart/form-data。此外还需要规定一个内容分割符用于分割请求体中不同参数的内容 (详细说明请打开该链接查看)。下面是一个能正常传输 FormData 数据的请求头:
可以看到 Content-Type 后面有一串复杂的代码。那个就是内容分割符。所以手动设置这些是很麻烦的。好在,如果我们对请求的 Content-Type 进行手动设置,浏览器会自动识别 FormData数据并设置 Content-Type 。
这也就是为什么不要设置 Content-Type 的原因了。在第一点我提及过上传文件的请求体添加其他参数时必须要添加到FormData。这是因为如果请求boby里如果存在非FormData数据类型时,浏览器就不会识别数据FormData。也就是,Content-Type不会自动添加为multipart/form-data,而是变成了application/json。这样一来,后端就拿不到文件数据了。
在使用axios时,我们有时会添加拦截器。在进行拦截器设置时也要考虑到FormData。如果是FormData数据就不要设置Content-Type了。
结语
文件上传需要用到<input type="file"/>
、FormData数据类型,在向后端发送数据是切忌设置 Content-Type 。