Form 元素
<form>
元素表示文档中的一个区域,此区域包含交互控件,用于向 Web 服务器提交信息(文件、字符)。下面称之为表单元素或表单。
要向 Web 服务器提交信息,我们必须要给表单内添加几个<input>
元素;它有一个用于指定提交信息的类型的属性type
,如:text、password、file 等。
表单本身有提交属性action
,指的是表单内的信息提交的 Web 服务器的请求地址:
<form id="form" action="http://localhost:8080/upload/user/info">
<input id="uname" type="text" name="uname" />
<input id="pwd" type="password" name="pwd" />
<button type="submit">submit</button>
</form>
当点击按钮(类型为 submit)时,表单就打包信息然后发送action
属性指定的 Web 服务器进行处理。
FormData
FormData 是一个接口,用它提交信息给 Web 服务器最终的效果是一样的。直接用表单元素可以不用 JS 代码就可以实现提交信息的功能。有了 FormData 自由度更高,本身提供了许多的方法供我们使用。
FormData 数据结构
仔细观察可以知道,表单元素其实就是一个 key/value
的集合,所以,FormData 也是这样的集合。FormData 接口只提供封装信息的能力,数据发送实际是交给XMLHttpRequest
来处理的。
XMLHttpRequest.send(body)
可以接收几种类型的数据,其中之一就是 FormData。
append() 和 set()
函数 | 作用 | 区别 |
---|---|---|
set(name, value) | 添加一个键值对到 FormData 中 | 如果有相同的 name(key),覆盖上一次的所有值 |
append(name, value) | 添加一个键值对到 FormData 中 | 如果有相同的 name(key),追加到 value 后面 |
append 和 set 都可以添加数据到 FormData 中。但是实际使用中有着很大的区别,下面将通过实验来证明。
set
formData.set('hobbies', 'football');
console.log(`第一次 value:${formData.getAll('hobbies')}`);
formData.set('hobbies', 'animation');
console.log(`第二次 value:${formData.getAll('hobbies')}`);
append
formData.append('hobbies', 'football');
console.log(`第一次 value:${formData.getAll('hobbies')}`);
formData.append('hobbies', 'animation');
console.log(`第二次 value:${formData.getAll('hobbies')}`);
通过实验证明,如果第二次添加的 key 与第一次的 key 是相同的,set 会覆盖第一次 value 中的数据;append 会追加到 value 之后。
多文件上传
前端
<div id="app">
<input @change="selected($event)" type="file" multiple />
<button @click="submit">提交</button>
</div>
Vue.createApp({
data() { return { files: [] }; },
methods: {
selected(e) { this.files = e.target.files; },
submit() {
let formData = new FormData();
for (let index in this.files) { formData.append(`files`, this.files[index]); }
axios.post('http://localhost:8080/upload/files', formData, {
headers: { 'content-type': 'multipart/form-data' }
});
}
}
}).mount('#app');
后端
MultipartFile
前端发送的请求体类型(Content-Type)是 multipart/form-data,需要用 MultipartFile 来解析。官方对 MultipartFile 的定义:Spring Web - MultipartFile。
编写接口
@PostMapping(value = "/upload/files", consumes = "multipart/form-data")
public void uploadFiles(@RequestParam("files") MultipartFile[] files) {
System.out.println(files[0].getOriginalFilename());
System.out.println(files[1].getOriginalFilename());
}
- consumes:表示此接口只能接收的请求体类型(Content-Type)是 multipart/form-data;
RequestBody:因为 POST 请求方式的数据都是在请求体(Body)中,所以用此注解接收数据;
MultipartFile:解析 multipart/form-data 的数据。