隐藏

IDEA-SpringBoot文件上传和下载

发布:2022/4/9 11:34:09作者:管理员 来源:本站 浏览次数:668

文件上传


开发Web应用时,文件上传是常见的需求,浏览器通过表单形式将文件以流的形式传递给服务器,服务器在对上传的数据解析处理。


   


   开发环境及代码见上一篇博客-SpringBoot整合Servlet三大组件

   编写文件上传的表单页面 upload.html


<!DOCTYPE html>

// 导入Thymeleaf配置

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

   <meta charset="UTF-8">

   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

   <title>动态添加文件上传列表</title>

   // 导入相关CSS配置文件 login为static文件夹下的文件,见静态文件导入

   <link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet">

   <script th:src="@{/login/js/jquery.min.js}"></script>

</head>

<body>

<div th:if="${uploadStatus}" style="color: red" th:text="${uploadStatus}">上传成功</div>

<form th:action="@{/uploadFile}" method="post" enctype="multipart/form-data">

   上传文件:&nbsp;&nbsp;<input type="button" value="添加文件" onclick="add()"/>

   <div id="file" style="margin-top: 10px;" th:value="文件上传区域">  </div>

   <input id="submit" type="submit" value="上传"

          style="display: none;margin-top: 10px;"/>

</form>

<script type="text/javascript">

   // 动态添加上传按钮

   function add(){

       var innerdiv = "<div>";

       innerdiv += "<input type='file' name='fileUpload' required='required'>" +

           "<input type='button' value='删除' οnclick='remove(this)'>";

       innerdiv +="</div>";

       $("#file").append(innerdiv);

       // 打开上传按钮

       $("#submit").css("display","block");

   }

   // 删除当前行<div>

   function remove(obj) {

       $(obj).parent().remove();

       if($("#file div").length ==0){

           $("#submit").css("display","none");

       }

   }

</script>

</body>

</html>


 

   全局配置文件配置


# Thymeleaf页面缓存设置(默认为true),开发中为方便调试应设置为false,上线稳定后保持默认true

spring.thymeleaf.cache=false

# 配置国际化文件基础名

spring.messages.basename=i18n.login

# 单个上传文件大小显示(默认1MB)

spring.servlet.multipart.max-file-size=10MB

# 总上传文件大小限制(默认为10MB)

spring.servlet.multipart.max-request-size=50MB


 


   实现文件上传功能和处理


/*

   文件管理控制类

*/

@Controller

public class FileController {

   // 向文件上传页面跳转

   // 处理路径为:"/toUpload的GET请求",并返回上传页面的路径

   @GetMapping("/toUpload")

   public String toUpload(){

       return "upload";

   }

   //文件上传管理

   // 处理"/uploadFile"的POST请求,如果文件上传成功,会将上传的文件重命名并存储在指定目录

   @PostMapping("/uploadFile")

   public String uploadFile(MultipartFile[] fileUpload, Model model){

       //默认文件上传成功,并返回状态信息

       model.addAttribute("uploadStatus","上传成功!");

       for(MultipartFile file: fileUpload){

           //获取文件名以及后缀名

           //file.getOriginalFilename()是得到上传时的文件名

           String fileName = file.getOriginalFilename();

           //重新生成文件名(根据具体情况生成对应文件名)

           //UUID.randomUUID():生成唯一识别码

           fileName = UUID.randomUUID()+"_"+fileName;

           //指定上传文件本地存储目录,不存在则需要提前创建

           String dirPath = "F:/file/";

           File filePath = new File(dirPath);

           if(!filePath.exists()){

               filePath.mkdirs();

           }

           try{

          //将file移动到targetfile目录下

               file.transferTo(new File(dirPath+fileName));

           }catch (Exception e){

               e.printStackTrace();

               model.addAttribute("uploadStatus","上传失败:"+e.getMessage());

           }

       }

       //携带上传状态信息回调到文件上传页面

       return "upload";

   }

}



   测试效果即可


文件下载


   下载文件能够通过IO流实现,所以多数框架并没有对文件下载进行封装处理。文件下载时设计不同浏览器的解析处理,可能会出现中文乱码的情况。

   英文名文件下载

   添加文件下载工具依赖


<dependency>

           <groupId>commons-io</groupId>

           <artifactId>commons-io</artifactId>

           <version>2.6</version>

      </dependency>


 


   定制文件下载页面download.html


<!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>xxxxx</td>

       //文件下载前需要保证文件下载目录中存在文件 xxxxx 自行存放

       <td><a th:href="@{/download(filename='xxxxx')}">下载文件</a></td>

   </tr>

   <tr>

       <td>xxxxx</td>

       <td><a th:href="@{/download(filename='xxxxx')}">

           下载文件</a></td>

   </tr>

</table>

</body>

</html>



   文件下载处理方法


// 向文件下载页面跳转

   @GetMapping("/toDownload")

   public String toDownload(){

       return "download.html";

   }

   // 文件下载管理

   @GetMapping("/download")

   public ResponseEntity<byte[]> fileDownload(String filename){

       // 指定要下载的文件根路径

       String dirPath = "F:/file/";

       // 创建该文件对象

       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("/toDownload")

   public String toDownload(){

       return "download.html";

   }

   // 文件下载管理

   @GetMapping("/download")

   public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception{

       // 指定要下载的文件根路径

       String dirPath = "F:/file/";

       // 创建该文件对象

       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 = {"MSTE","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(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);

   }


 


   测试通过可以下载中文名文件不出现编码问题