表单提交与后端接收

HTML中的表单有几个重要的属性,分别是actionmethodenctype

  • action:用于设定表单提交的服务器的 URL,可以是相对路径和绝对路径。
  • method:用于设定 HTTP 请求的方式。
  • enctype:用于定义表单数据提交到服务器的过程中如何对数据进行编码

本次主要针对enctype进行测试实验。method统一使用POST方式。

后端使用SpringBoot2.x,Spring在参数处理方面已经做了很好的处理了。

SpringBoot上传文件的一些基本设置

  1. #是否开启文件上传支持,默认是true
  2. spring.servlet.multipart.enabled=true
  3. spring.servlet.multipart.max-request-size=100MB
  4. spring.servlet.multipart.max-file-size=10MB
  5. #文件写入磁盘的阈值,默认是0,这意味着文件将立即写入磁盘
  6. spring.servlet.multipart.file-size-threshold=0

application/x-www-form-urlencoded方式

默认方式是第一种 application/x-www-form-urlencoded,当使用 form 表单提交数据时,会对数据进行编码。

前端代码:

  1. <form id="form" action="http://localhost:8080/form/test" method="POST" enctype="application/x-www-form-urlencoded">
  2. name<input type="text" name="name" id="name">
  3. age<input type="text" name="age" id="age">
  4. submit<input type="submit">
  5. </form>

后端接收方式

  1. // 实体类
  2. @Data
  3. public class Person
  4. {
  5. private String name;
  6. private Integer age;
  7. }
  8. // 控制器
  9. @CrossOrigin("*")
  10. @RestController
  11. @RequestMapping("/form")
  12. public class FormController
  13. {
  14. @PostMapping("/test")
  15. public void test(Person person)
  16. {
  17. System.out.println(person);
  18. }
  19. }

application/x-www-form-urlencoded方式的表单提交,后端可以直接使用实体类接收,但是要注意HTML中的input的name属性值要对应实体类的属性名

application/json方式

使用AJAX提交JSON格式的数据是很常见的,处理的方式也较为简单

前端JS如下:

  1. function submit() {
  2. $.ajax({
  3. type: 'POST',
  4. url: 'http://localhost:8089/form/test',
  5. // 传送到后端应为JSON格式字符串,使用JSON的stringify方法格式化
  6. data: JSON.stringify(
  7. {
  8. name: $("#name"),
  9. age: $("#age")
  10. }
  11. ),
  12. // 必须为该格式
  13. contentType: 'application/json',
  14. dataType: 'json',
  15. success: (res) => {
  16. alert(res);
  17. }
  18. });
  19. }

后端接收,只需要在参数前添加@RequestBody注解,Spring会自动解析映射。

  1. @PostMapping("/test")
  2. public void test(@RequestBody Person person)
  3. {
  4. System.out.println(person);
  5. }

multipart/form-data

当设置成 multipart/form-data 时,浏览器不对字符进行编码,每一个域都是一个part、这种编码方式通常适用于上传文件。

当不上传文件,只提交表单数据时,后端接收方式与application/x-www-form-urlencoded一致。

当既要上传文件又要提交额外的数据时,前端可以使用FormData对象封装参数。


单文件上传

直接使用from表单提交,前端如下:

  1. <form id="form">
  2. file<input type="file" id="file" name=file>
  3. name<input type="text" name="name" id="name">
  4. age<input type="text" name="age" id="age">
  5. submit<input type="submit">
  6. </form>

后端:

  1. @PostMapping("/file")
  2. public void fileTest(@RequestParam("file") MultipartFile file, Person person)
  3. {
  4. System.out.println(person);
  5. System.out.println(file.getOriginalFilename());
  6. }

multipart/form-data这种方式提交时,参数都是binary类型

表单提交 - 图1

通过AJAX使用FormData对象封装参数后提交,前端JS如下:

  1. function submit() {
  2. let formData = new FormData();
  3. let file = $("#file")[0].files[0];
  4. formData.append("name", $("#name2").val());
  5. formData.append("age", $("#age2").val());
  6. console.log(formData);
  7. $.ajax({
  8. type: 'POST',
  9. url: 'http://localhost:8089/form/files',
  10. data: formData,
  11. cache: false,
  12. processData: false,
  13. contentType: false,
  14. dataType: 'json',
  15. success: (res) => {
  16. alert(res);
  17. }
  18. });
  19. }

将Person的参数拼接进FormData对象中,提交的时候,name和age的参数不再是binary。但Spring同样可以像上面那种方式一样将参数解析出来。注意append时的key值对应实体类属性名

后端如下方式接收:

  1. @PostMapping("/file")
  2. public void fileTest(@RequestParam("file") MultipartFile file, Person person)
  3. {
  4. System.out.println(person);
  5. System.out.println(file.getOriginalFilename());
  6. }

还有一种更加优雅的方式,将Person拼接的时候也使用binary格式,但要指定type为application/json

  1. function submit() {
  2. let formData = new FormData();
  3. let file = $("#file")[0].files[0];
  4. let person = {
  5. name: $("#name2").val(),
  6. age: $("#age2").val()
  7. }
  8. // 将person转为json字符串
  9. formData.append('person', new Blob([JSON.stringify(person)], { type: 'application/json' }));
  10. console.log(formData);
  11. $.ajax({
  12. type: 'POST',
  13. url: 'http://localhost:8089/form/files',
  14. data: formData,
  15. cache: false,
  16. processData: false,
  17. contentType: false,
  18. dataType: 'json',
  19. success: (res) => {
  20. alert(res);
  21. }
  22. });
  23. }

后端接收时使用@RequestPart注解将映射Person参数

  1. @PostMapping("/files")
  2. public void fileTest(@RequestParam("file") MultipartFile file, @RequestPart("person") Person person)
  3. {
  4. System.out.println(person);
  5. System.out.println(file.getOriginalFilename());
  6. }

多文件上传

前端有两种写法、一种是使用HTML5的multiple属性创建一个支持多选文件的上传框,一种是写多个上传框。

  1. 第一种:HTML5的multiple属性创建一个支持多选文件的上传框
    1. <form id="form">
    2. file<input type="file" multiple="multiple" id="files" name=files>
    3. name<input type="text" name="name" id="name">
    4. age<input type="text" name="age" id="age">
    5. </form>


js如下

  1. function submit() {
  2. let formData = new FormData();
  3. let files = $("#files");
  4. let person = {
  5. name: $("#name").val(),
  6. age: $("#age").val()
  7. }
  8. // 循环遍历files输入框、拼接文件内容到formData
  9. for (let i = 0; i < files[0].files.length; i++) {
  10. formData.append("files", files[0].files[i]);
  11. }
  12. formData.append('person', new Blob([JSON.stringify(person)], { type: 'application/json' }));
  13. console.log(formData);
  14. $.ajax({
  15. type: 'POST',
  16. url: 'http://localhost:8089/form/files',
  17. data: formData,
  18. cache: false,
  19. processData: false,
  20. contentType: false,
  21. dataType: 'json',
  22. success: (res) => {
  23. alert(res);
  24. }
  25. });
  26. }
  1. 使用多个上传框
    1. <form id="form">
    2. file<input type="file" name=files id="file1">
    3. file<input type="file" name=files id="file2">
    4. name<input type="text" name="name" id="name2">
    5. age<input type="text" name="age" id="age2">
    6. </form>


js代码如下

  1. function submit2() {
  2. let formData = new FormData();
  3. let file1 = $("#file1")[0].files[0];
  4. let file2 = $("#file2")[0].files[0];
  5. let person = {
  6. name: $("#name2").val(),
  7. age: $("#age2").val()
  8. }
  9. formData.append("files", file1);
  10. formData.append("files", file2);
  11. formData.append('person', new Blob([JSON.stringify(person)], { type: 'application/json' }));
  12. console.log(file1);
  13. $.ajax({
  14. type: 'POST',
  15. url: 'http://localhost:8089/form/files',
  16. data: formData,
  17. cache: false,
  18. processData: false,
  19. contentType: false,
  20. dataType: 'json',
  21. success: (res) => {
  22. alert(res);
  23. }
  24. });
  25. }

后端接收方式第一样、只需要将接收文件的MultipartFile设为数组即可

  1. @PostMapping("/files")
  2. public void fileTest(@RequestParam("files") MultipartFile[] files, @RequestPart("person") Person person)
  3. {
  4. System.out.println(person);
  5. System.out.println(files.length);
  6. }