<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.itheima</groupId> <artifactId>uploadAndDowload</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> </plugins> </build> </project>
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>文件下载</title> </head> <body> <div style="margin-bottom: 10px">文件下载列表:</div> <table> <tr> <td>新建 DOCX 文档.docx</td> <td><a th:href="@{/download(filename='新建 DOCX 文档.docx')}">下载文件</a></td> </tr> <tr> <td>b89bc016-d2d6-428d-b9ae-39a2a1e70d86_Dump20200624.sql</td> <td><a th:href="@{/download(filename='b89bc016-d2d6-428d-b9ae-39a2a1e70d86_Dump20200624.sql')}"> 下载文件</a></td> </tr> </table> </body> </html>
package com.itheima.controller; import java.io.File; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; @Controller public class FileController { // 向文件上传页面跳转 @GetMapping("/toUpload") public String toUpload() { return "upload"; } // 文件上传管理 @PostMapping("/uploadFile") public String uploadFile(MultipartFile[] fileUpload, Model model) { // 默认文件上传成功,并返回状态信息 model.addAttribute("uploadStatus", "上传成功!"); for (MultipartFile file : fileUpload) { // 获取文件名以及后缀名 String fileName = file.getOriginalFilename(); // 重新生成文件名(根据具体情况生成对应文件名) fileName = UUID.randomUUID() + "_" + fileName; // 指定上传文件本地存储目录,不存在需要提前创建 String dirPath = "D:/copy/"; File filePath = new File(dirPath); if (!filePath.exists()) { filePath.mkdirs(); } try { file.transferTo(new File(dirPath + fileName)); } catch (Exception e) { e.printStackTrace(); // 上传失败,返回失败信息 model.addAttribute("uploadStatus", "上传失败: " + e.getMessage()); } } // 携带上传状态信息回调到文件上传页面 return "upload"; } // 向文件下载页面跳转 @GetMapping("/toDownload") public String toDownload() { return "download"; } // 文件下载管理 @GetMapping("/download") public ResponseEntity<byte[]> fileDownload(String filename){ // 指定要下载的文件根路径 String dirPath = "D:/copy/"; // 创建该文件对象 File file = new File(dirPath + File.separator + filename); // 设置响应头 HttpHeaders headers = new HttpHeaders(); // 通知浏览器以下载方式打开 headers.setContentDispositionFormData("attachment",filename); // 定义以流的形式下载返回文件数据 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); try { return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity<byte[]>(e.getMessage().getBytes(),HttpStatus.EXPECTATION_FAILED); } } }
下面是处理下载文件名包含中文的时候字符编码问题。
// 所有类型文件下载管理 @GetMapping("/download") public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception { // 指定要下载的文件根路径 String dirPath = "D:/copy/"; // 创建该文件对象 File file = new File(dirPath + File.separator + filename); // 设置响应头 HttpHeaders headers = new HttpHeaders(); // 通知浏览器以下载方式打开(下载前对文件名进行转码) filename = getFilename(request, filename); headers.setContentDispositionFormData("attachment", filename); // 定义以流的形式下载返回文件数据 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); try { return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity<byte[]>(e.getMessage().getBytes(), HttpStatus.EXPECTATION_FAILED); } } // 根据浏览器的不同进行编码设置,返回编码后的文件名 private String getFilename(HttpServletRequest request, String filename) throws Exception { // IE不同版本User-Agent中出现的关键词 String[] IEBrowserKeyWords = { "MSIE", "Trident", "Edge" }; // 获取请求头代理信息 String userAgent = request.getHeader("User-Agent"); for (String keyWord : IEBrowserKeyWords) { if (userAgent.contains(keyWord)) { // IE内核浏览器,统一为UTF-8编码显示,并对转换的+进行更正 return URLEncoder.encode(filename, "UTF-8").replace("+", " "); } } // 火狐等其它浏览器统一为ISO-8859-1编码显示 return new String(filename.getBytes("UTF-8"), "ISO-8859-1"); }