前言
本文介绍前端HTML界面如何向后端发送文件的两种方式: form表单上传和Ajax上传两种方式,本文是基于Spring Boot项目的Web应用。之前在解决文件上传问题时走了不少弯路,在项目完成以后写下博客来记录自己的解决方法,以后再遇到类似的问题将不会再发生之前犯过的错误,如果内容有解释描述不妥之处,欢迎在评论区指出。
送给阅读本文读者的一段话:之前做项目时这些方法我也不会,在实现的过程中也是一直遇到各种各样的问题,我也查阅了网络上很多的博客和案例。但是我在点开博客时看到没有讲解只有代码时就立刻关闭,没有静下心来去好好的理解代码,可能有很多读者和我的心态是一样的,所以在这里想跟和我以前一样心态的读者说一句:亲爱的读者朋友,感谢你点开这篇文章,如果你和我一样有很焦急迫切的心态的话,希望此刻你能静下心来看一看我写的内容,我相信咱们遇到的问题是相似的,有了之前自己希望博文中能够出现的内容,所以我会在博文中加入相应的内容。再次感谢你能看到这里,我也自信我的这篇博文能够帮助到你。
本文案例基于SpringBoot实现,以上传Excel文件为例,因为这里只涉及到了Controller层,pom.xml文件中的依赖以及其余层的内容在此不多做赘述
一、form表单上传
1、样例代码:
HTML代码
<!DOCTYPE html> <html> <head> <title>上传文件</title> <meta content="text/html" charset="UTF-8"> </head> <body> <h1>上传文件</h1> <form action="/upload" enctype="multipart/form-data" method="post"> <table> <tr> <td>文件描述:</td> <td><input type="text" name="mess"></td> </tr> <tr> <td>选择文件:</td> <td><input type="file" id="file" name="file"></td> </tr> <tr> <td><input type="submit" value="上传" name="btn" id="btn"></td> </tr> </table> </form> </body> </html>
Controller层代码
package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; /** * @author Dream_飞翔 * @email 1072876976@qq.com */ @Controller public class MessController { @RequestMapping("upload") @ResponseBody public String upLoad(String mess, MultipartFile file){ System.out.println(mess); System.out.println(file.getOriginalFilename()); return "success"; } }
2、运行结果:
3、代码解析:
HTML代码
<form action="/upload" enctype="multipart/form-data" method="post"> ... </form>
在利用form表单上传文件时要将enctype属性的属性值设置为multipart/form-data,其次要将method的属性值设置为post ,action属性的值为请求的路径(与Controller层中的@requestMapping注解中的值对应,注意要加" / ")
原因
1、enctype属性的属性值设置为multipart/form-data
enctype="multipart/form-data"的意思其实就是设置表单的MIME编码。默认情况的编码格式是application/x-www-form-urlencoded,将表单中的数据变为键值对的形式,不能用于文件的上传。而enctype="multipart/form-data"是将表单中的数据变成二进制数据进行上传(也就是说将文件转换成二进制数据进行上传)。
2、method的属性值设置为post
method的属性值设置为post有多种原因,其中最主要的原因就是:Get方式是用来从服务器上获得数据,而 Post方式是用来向服务器上传递数据 ,其次就是Get 是不安全的,因为在传输过程,数据被放在请求的URL中,除了可能会有一些隐私的信息被第三方看到外,用户也可以在浏览器上直接看到提交的数据,一些系统内部消息将会一同显示在用户面前。而Post 的所有操作对用户来说都是不可见的。
Controller层代码
@RequestMapping("upload") @ResponseBody public String upLoad(String mess, MultipartFile file){ ... return "success"; }
注解解析:
第一行注解的意思为截取到请求名称为upload的动作,这里的值与HTML页面中form表单中的action的属性值一致.,本质上就是将action的动作截取到,执行注解对应方法中的方法体内容 (在SpringMVC的源码中处理页面请求时用到的底层技术还是Servlet)第二行注解的意思,在解释第二行代码的意思前先看方法头的返回值为String类型,在Controller层中当方法的返回值为String类型时有两种情况,当方法头前加有@ResponseBody注解时,return的内容将会展示在前端页面上。注意:此时返回前端的是Json对象而不是Json串;当方法头前不加@responseBody注解时将会跳转到对应名称的HTML界面,所以此时当文件上传成功后将"success"打印到前端界面上
方法解析:
返回值类型为String类型,因为在方法头前加有@ResponseBody注解,因此当文件上传成功后会将return的内容打印到前端显示。第一个参数是获取到前端form表单中的输入的文字信息,对应前端如下语句:
<td>文件描述:</td> <td><input type="text" name="mess"></td>
第二个参数是MultipartFile本质上是SpringMVC框架为我们提供简化上传操作的工具类,在前端HTML页面上传文件时是将文件转换成二进制字节流来传到后端,如果不使用MultipartFile工具类的话我们只能用HttpServletRequest来接收上传的数据,再手动将二进制流转化为File文件。MultipartFile的出现简化了我们的操作,此时file就是我们传到后端的文件。
file.getOriginalFilename()
getOriginalFilename()为获取到文件的名称
二、Ajax上传
1、样例代码:
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Ajax上传文件</title> <script type="text/javascript" src="/js/jquery-3.5.1.min.js"></script> </head> <body> <h1>Ajax上传文件</h1> <table> <tr> <td>文件上传</td> </tr> <tr> <td>文件描述:</td> <td><input type="text" name="mess" id="mess"></td> </tr> <tr> <td>上传文件</td> <td><input type="file" name="file" id="upfile"></td> </tr> <tr> <td><input type="submit" onclick="checkFile()" value="上传"/></td> </tr> </table> </body> <script> // 在使用Ajax上传文件之前要先导入jQuery function checkFile() { var formData = new FormData(); formData.append('file', $('#upfile')[0].files[0]); $.ajax({ url:"/uploadSecond", type:"POST", data:formData, cache:false, processData:false, contentType:false, dataType: 'json', success:function (data) { // console.log(data); if (data == "1") alert("上传成功"); }, error:function (data) { if (data == "0") alert("上传失败"); } }); } </script> </html>