文件上传
开发Web应用时,文件上传是很常见的一个需求,浏览器通过表单形式将文件以流的形式传递给服务器,服务器对上传的数据解析处理。下面通过一个案例讲解如何使用Spring Boot实现文件上传,具体步骤如下:
1. 编写文件上传的表单页面
在chapter05项目根路径下的templates模板引擎文件夹下创建一个用来上传文件的upload.html模板页面,内容如文件1所示。
文件1 upload.html
1 <!DOCTYPE html>
2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3 <head>
4 <meta charset="UTF-8">
5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
6 <title>动态添加文件上传列表</title>
7 <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">
8 <script th:src="@{/login/js/jquery.min.js}"></script>
9 </head>
10 <body>
11 <div th:if="${uploadStatus}" style="color: red" th:text="${uploadStatus}">上传成功</div>
12 <form th:action="@{/uploadFile}" method="post" enctype="multipart/form-data">
13 上传文件: <input type="button" value="添加文件" onclick="add()"/>
14 <div id="file" style="margin-top: 10px;" th:value="文件上传区域"> </div>
15 <input id="submit" type="submit" value="上传"
16 style="display: none;margin-top: 10px;"/>
17 </form>
18 <script type="text/javascript">
19 // 动态添加上传按钮
20 function add(){
21 var innerdiv = "<div>";
22 innerdiv += "<input type='file' name='fileUpload' required='required'>" +
23 "<input type='button' value='删除' onclick='remove(this)'>";
24 innerdiv +="</div>";
25 $("#file").append(innerdiv);
26 // 打开上传按钮
27 $("#submit").css("display","block");
28 }
29 // 删除当前行<div>
30 function remove(obj) {
31 $(obj).parent().remove();
32 if($("#file div").length ==0){
33 $("#submit").css("display","none");
34 }
35 }
36 </script>
37 </body>
38 </html>
文件1的内容主要分为3部分内容,第12~17行的<form>表单用来封装上传文件标签并进行表单提交,第11行中<form>表单上方的文件上传状态信息uploadStatus,第10~36行的<script>标签中用于动态添加/删除上传标签的方法。其中,<form>表单中进行文件上传时,必须设置enctype="multipart/form-data",并将method属性设置为post;<script>标签中的add和remove方法用于根据用户上传文件需求动态添加或移除上传输入框效果的。
另外在文件1中第8行代码还引入了静态资源目录下的login/js中的jquery.min.js文件,因此,这里需要在项目resources/static/login目录下创建一个js文件夹,并引入jquery.min.js文件。
1. 在全局配置文件中添加文件上传的相关配置
在全局配置文件application.properties中添加文件上传功能的相关设置,内容如文件2所示。
文件2 application.properties
1 # thymeleaf页面缓存设置(默认为true),开发中方便调试应设置为false,上线稳定后应保持默认true
2 spring.thymeleaf.cache=false
3 # 配置国际化文件基础名
4 spring.messages.basename=i18n.login
5 # 单个上传文件大小限制(默认1MB)
6 spring.servlet.multipart.max-file-size=10MB
7 # 总上传文件大小限制(默认10MB)
8 spring.servlet.multipart.max-request-size=50MB
文件2中,在项目全局配置文件application.properties已有配置的基础上,对文件上传过程中的上传大小进行了设置。其中,spring.servlet.multipart.max-file-size用来设置单个上传文件的大小限制,默认值为1MB;spring.servlet.multipart.max-request-size用来设置所有上传文件的大小限制,默认值为10MB。如果上传文件的大小超出默认值10MB,会出现“FileUploadBase$FileSizeLimitExceededException: The field fileUpload exceeds its maximum permitted size of 1048576 bytes”异常信息,这里需要开发者结合实际需求合理设置文件大小。
2. 进行文件上传处理实现文件上传功能
在之前创建的com.itheima.controller包下创建一个管理文件上传下载的控制类FileController,用于实现文件上传功能,内容如文件3所示。
文件3 FileController.java
1 import org.springframework.stereotype.Controller;
2 import org.springframework.ui.Model;
3 import org.springframework.web.bind.annotation.*;
4 import org.springframework.web.multipart.MultipartFile;
5 import java.io.File;
6 import java.util.UUID;
7 /**
8 * 文件管理控制类
9 */
10 @Controller
11 public class FileController {
12 // 向文件上传页面跳转
13 @GetMapping("/toUpload")
14 public String toUpload(){
15 return "upload";
16 }
17 // 文件上传管理
18 @PostMapping("/uploadFile")
19 public String uploadFile(MultipartFile[] fileUpload, Model model) {
20 // 默认文件上传成功,并返回状态信息
21 model.addAttribute("uploadStatus", "上传成功!");
22 for (MultipartFile file : fileUpload) {
23 // 获取文件名以及后缀名
24 String fileName = file.getOriginalFilename();
25 // 重新生成文件名(根据具体情况生成对应文件名)
26 fileName = UUID.randomUUID()+"_"+fileName;
27 // 指定上传文件本地存储目录,不存在需要提前创建
28 String dirPath = "F:/file/";
29 File filePath = new File(dirPath);
30 if(!filePath.exists()){
31 filePath.mkdirs();
32 }
33 try {
34 file.transferTo(new File(dirPath+fileName));
35 } catch (Exception e) {
36 e.printStackTrace();
37 // 上传失败,返回失败信息
38 model.addAttribute("uploadStatus","上传失败: "+e.getMessage());
39 }
40 }
41 // 携带上传状态信息回调到文件上传页面
42 return "upload";
43 }
44 }
文件3中,toUpload()方法处理路径为“/toUpload”的GET请求,向文件上传页面upload.html跳转;uploadFile()方法处理路径为“/uploadFile”的POST请求,对上传文件进行处理。文件上传处理过程中,对文件名进行重命名并存放在“F:/file/”目录下,并封装了返回结果。其中,处理上传文件的请求方法中,使用了“MultipartFile[] fileUpload”参数处理单个或多个上传文件(也可以使用单列集合参数),fileUpload参数名必须与upload.html页面中上传文件<input>框中的name属性值一致。
1. 效果测试
启动项目,项目启动成功后,在浏览器上访问“http://localhost:8080/toUpload
”,效果如图1所示。
图1 文件上传页面初始效果
单击图2中的【添加文件】按钮,能够动态添加多个文件,效果如图2所示。
图2 文件上传页面动态添加文件效果
如图2所示,在文件上传页面中动态添加了3个上传文件输入框,分别选择了doc、xlsx和pptx格式的文件进行上传。其中,在每一个上传文件输入框后还有对应的【删除】按钮,通过这个按钮可以将多余的上传文件输入框移除;同时,如果在单击【上传】按钮进行文件上传时有未选择的文件输入框,还会出现“请选择一个文件”的提示信息(通过页面required属性进行控制的)。
单击图2中的【上传】按钮进行上传处理,效果如图3所示。
图3 文件上传响应
如图4所示,选择的3个文件进行上传处理后页面出现了“上传成功!”的响应信息。为了验证文件上传处理效果,查看定制的上传文件存储目录“F:/file/”,效果如图4所示。
图4 文件上传处理结果
从图4可以看出,在定制的上传文件存储目录“F:/file/”下,出现了选择上传的3个不同类型的文件,同时文件名也根据设置进行了相应的修改,读者还可以打开每个文件查看具体的文件内容。