工作中上传文件是常见的场景之一,最典型的情况就是上传头像等,上传文档。自己上传文件中遇到的坑,自己已经填了,现在把它写下来,方便提醒自己,我使用的是Spring Boot 上传文件
Pom
主要引入了web和thymeleaf启动器
1 2 3 4 5 6 7 8 9 10
| <!-- web start--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- web end--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
|
yml
1 2 3 4 5 6 7 8
| spring: servlet: multipart: max-file-size: 10MB # 最大支持文件大小 max-request-size: 10MB # 最大支持请求大小 #enabled: true #默认支持文件上传. # file-size-threshold: #支持文件写入磁盘. #location: #上传文件的临时目录
|
controller
UploadController
UploadController首页的显示
1 2 3 4 5 6 7 8 9
| @Controller public class UploadController {
@GetMapping("/") public String index() { return "upload"; }
}
|
FileController
FileController文件上传,下载请求
文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| /** * @author: 三月三 * @description: 单个文件上传 * @param: [file] * @return: java.lang.String */ @RequestMapping(value = "/upload") public String upload(HttpServletRequest request, @RequestParam("file") MultipartFile file, Model model) { // 测试MultipartFile接口的各个方法 System.out.println("文件类型ContentType=" + file.getContentType()); System.out.println("文件组件名称Name=" + file.getName()); System.out.println("文件原名称OriginalFileName=" + file.getOriginalFilename()); System.out.println("文件大小Size=" + file.getSize()/1024 + "KB"); try { if (file.isEmpty()) { return "文件为空"; } // 获取文件名 String fileName = file.getOriginalFilename(); log.info("上传的文件名为:" + fileName); // 获取文件的后缀名 String suffixName = fileName.substring(fileName.lastIndexOf(".")); log.info("文件的后缀名为:" + suffixName);
// 获取文件相对类路径 //String filePath = request.getServletContext().getRealPath("/"); //文件绝对路径,项目中一般使用相对类路径,即使文件变更路径也会跟着变 String filePath = request.getServletContext().getRealPath("G:\\dev_workspace\\springboot-learning-examples\\springboot-13-fileupload\\src\\main\\resources\\static"); System.out.println("path = " + filePath); //构造一个路径 String newImg = UUID.randomUUID()+suffixName; String path = filePath + newImg; log.info("构造路径"+path);
File dest = new File(path); // 检测是否存在目录 if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs();// 新建文件夹 } file.transferTo(dest);// 文件写入 model.addAttribute("msg","<font color=\"green\">上传成功</font>"); model.addAttribute("img",newImg); return "upload"; } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } model.addAttribute("msg","<font color=\"green\">上传失败</font>"); return "upload"; }
|
多文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| /** * @author: 三月三 * @description: 多个文件上传 * @param: [request] * @return: java.lang.String */ @PostMapping("/batch") public String handleFileUpload(Model model,HttpServletRequest request) { List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file"); MultipartFile file = null; BufferedOutputStream stream = null; for (int i = 0; i < files.size(); ++i) { file = files.get(i); //文件绝对路径,项目中一般使用相对类路径,即使文件变更路径也会跟着变 String filePath = request.getServletContext().getRealPath("G:\\dev_workspace\\springboot-learning-examples\\springboot-13-fileupload\\src\\main\\resources\\static"); if (!file.isEmpty()) { try { byte[] bytes = file.getBytes(); stream = new BufferedOutputStream(new FileOutputStream( new File(filePath + file.getOriginalFilename())));//设置文件路径及名字 stream.write(bytes);// 写入 stream.close(); } catch (Exception e) { stream = null;
model.addAttribute("msg", "第 " + i + " 个文件上传失败 ==> " + e.getMessage()); return "upload"; } } else { model.addAttribute("msg","第 " + i + " 个文件上传失败因为文件为空"); return "upload"; } } model.addAttribute("msg","上传成功"); return "upload"; }
|
文件下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| /** * @author: 三月三 * @description: 文件下载 * @param: [model, request, response, fileName] * @return: java.lang.String */ @PostMapping("/download") public String downloadFile(Model model,HttpServletRequest request, HttpServletResponse response,String fileName) { if (fileName != null) { //设置文件路径 真实环境是存放在数据库中的 // String filePath = request.getServletContext().getRealPath("/"); //文件绝对路径,项目中一般使用相对类路径,即使文件变更路径也会跟着变 String filePath = request.getServletContext().getRealPath("G:\\dev_workspace\\springboot-learning-examples\\springboot-13-fileupload\\src\\main\\resources\\static"); File file = new File(filePath); if (file.exists()) { response.setContentType("application/force-download");// 设置强制下载不打开 response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名 byte[] buffer = new byte[1024]; FileInputStream fis = null; BufferedInputStream bis = null; try { fis = new FileInputStream(file);
bis = new BufferedInputStream(fis); // 创建输出对象 OutputStream os = response.getOutputStream(); int i = bis.read(buffer); while (i != -1) { os.write(buffer, 0, i); i = bis.read(buffer); } model.addAttribute("msg","<font color=\"green\">下载成功</font>"); return "upload"; } catch (Exception e) { e.printStackTrace(); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } } model.addAttribute("msg","<font color=\"red\">下载失败</font>"); return "upload"; }
|
页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <body>
<h1>Spring Boot file upload example</h1>
<p>单文件上传</p> <form action="upload" method="POST" enctype="multipart/form-data"> 文件:<input type="file" name="file"/> <input type="submit"/> </form>
<span th:if="${msg!=null}" th:utext="${msg}"></span>
<div th:if="${img!=null}"> <img th:src="${img}"> <p>文件下载</p> <form action="download" method="post"> <input type="hidden" th:value="${img}" name="fileName"/> <input type="submit" value="下载文件"/> </form> </div>
<p>多文件上传</p> <form method="POST" enctype="multipart/form-data" action="batch"> <p>文件1:<input type="file" name="file"/></p> <p>文件2:<input type="file" name="file"/></p> <p><input type="submit" value="上传"/></p> </form> </body> </html>
|
BUG
- 文件上传路径问题
- 文件下载的路径问题
解决:
String filePath = request.getServletContext().getRealPath("/");获取的是tomcat目录下webapps下的目录及类路径(class文件存放的路径),因为我使用的是SpringBoot项目,而SringBoot项目内嵌了tomcat,路径为C:\Users\L15096000421\AppData\Local\Temp\tomcat-docbase.2191751665660359817.8080\的一个临时目录
- 还是使用
String filePath = request.getServletContext().getRealPath("/")做为下载的路径去下载文件,后台报错没有权限,使用绝对路径下载,及使用绝对路径上传