当前位置:   article > 正文

Spring MVC的高级功能——文件上传和下载(三)文件上传和下载

Spring MVC的高级功能——文件上传和下载(三)文件上传和下载

一、案例的功能需求

        接下来将文件上传和下载的相关知识结合起来,实现一个文件上传和下载的案例。在实现案例之前,首先分析案例的功能需求。本案例要实现的功能为,将文件上传到项目的文件夹下,文件上传成功后将上传的文件名称记录到一个文件中,并将记录的文件列表展示在页面,单击文件列表的链接实现文件下载。

二、实现文件上传和下载案例的思路

•    搭建文件上传和下载的环境。
•    实现文件上传功能。
•    实现获取文件列表功能。
•    编写文件上传和下载页面。
•    实现文件下载。

接下来按照分析思路实现文件上传和下载,具体步骤如下所示。

        1、搭建文件上传和下载的环境:在项目的pom.xml中引入commons-fileupload的依赖,具体代码如下所示。

  1. <dependency>
  2. <groupId>commons-fileupload</groupId>
  3. <artifactId>commons-fileupload</artifactId>
  4. <version>1.4</version>
  5. </dependency>

                在spring-mvc.xml中配置多部件解析器,具体配置如下所示。

  1. <bean id="multipartResolver" class=
  2. "org.springframework.web.multipart.commons.CommonsMultipartResolver">
  3. <property name="defaultEncoding" value="UTF-8" />
  4. <property name="maxUploadSize" value="2097152" />
  5. </bean>

2、实现文件上传功能

(1)创建一个名称为files.json的记录文件。

        为了便于对files.json文件内容的存取,创建和files.json内容对应的资源类Resource,Resource类的具体代码如下所示。

  1. public class Resource {
  2. private String name; //name属性表示文件名称
  3. public Resource() {
  4. }
  5. public Resource(String name) {
  6. this.name = name;
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. }

(2)创建名称为JSONFileUtils的工具类。

  1. import org.apache.commons.io.IOUtils;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. public class JSONFileUtils {
  5. public static String readFile(String filepath) throws Exception {
  6. FileInputStream fis = new FileInputStream(filepath);
  7. return IOUtils.toString(fis);
  8. }
  9. public static void writeFile(String data, String filepath)
  10. throws Exception {
  11. FileOutputStream fos = new FileOutputStream(filepath);
  12. IOUtils.write(data, fos);
  13. }
  14. }

        (3)创建名称为FileController的控制器类,在FileController类中定义处理文件上传的方法fileUpLoad(),fileUpLoad()方法用于保存客户端上传的文件和文件的名称。保存上传的文件之前,先将上传文件的名称和files.json文件中的文件名称进行比较,如果files.json文件中已经有同名文件,则将上传文件的名称与字符串("1")拼接,生成新的文件名称并保存。上传文件保存成功后,将保存的文件的名称存入到files.json中。

  1. import com.fasterxml.jackson.core.type.TypeReference;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.itheima.pojo.Resource;
  4. import com.itheima.utils.JSONFileUtils;
  5. import org.apache.commons.io.FileUtils;
  6. import org.springframework.http.HttpHeaders;
  7. import org.springframework.http.HttpStatus;
  8. import org.springframework.http.MediaType;
  9. import org.springframework.http.ResponseEntity;
  10. import org.springframework.stereotype.Controller;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.ResponseBody;
  13. import org.springframework.web.multipart.MultipartFile;
  14. import sun.misc.BASE64Encoder;
  15. import javax.servlet.http.HttpServletRequest;
  16. import javax.servlet.http.HttpServletResponse;
  17. import java.io.File;
  18. import java.net.URLEncoder;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. @Controller
  22. public class FileController {
  23. /**
  24. * 文件上传
  25. */
  26. @RequestMapping("fileload")
  27. public String fileLoad(MultipartFile[] files,
  28. HttpServletRequest request) throws Exception {
  29. //设置上传的文件所存放的路径
  30. String path = request.getServletContext().getRealPath("/") + "files/";
  31. ObjectMapper mapper = new ObjectMapper();
  32. if (files != null && files.length > 0) {
  33. //循环获取上传的文件
  34. for (MultipartFile file : files) {
  35. //获取上传文件的名称
  36. String filename = file.getOriginalFilename();
  37. ArrayList<Resource> list = new ArrayList<>();
  38. //读取files.json文件中的文件名称
  39. String json = JSONFileUtils.readFile(path + "/files.json");
  40. if (json.length() != 0) {
  41. //将files.json的内容转为集合
  42. list = mapper.readValue(json,
  43. new TypeReference<List<Resource>>() {
  44. });
  45. for (Resource resource : list) {
  46. //如果上传的文件在files.json文件中有同名文件,将当前上传的文件重命名,以避免重名
  47. if (filename.equals(resource.getName())) {
  48. String[] split = filename.split("\\.");
  49. filename = split[0] + "(1)." + split[1];
  50. }
  51. }
  52. }
  53. // 文件保存的全路径
  54. String filePath = path + filename;
  55. // 保存上传的文件
  56. file.transferTo(new File(filePath));
  57. list.add(new Resource(filename));
  58. json = mapper.writeValueAsString(list); //将集合中转换成json
  59. //将上传文件的名称保存在files.json文件中
  60. JSONFileUtils.writeFile(json, path + "/files.json");
  61. }
  62. request.setAttribute("msg", "(上传成功)");
  63. return "forward:fileload.jsp";
  64. }
  65. request.setAttribute("msg", "(上传失败)");
  66. return "forward:fileload.jsp";
  67. }
  68. }

3、实现获取文件列表功能

        在FileController中新增获取文件列表的方法getFilesName(),getFilesName()方法获取files.json文件中的内容,并且以JSON格式返回数据。

  1. @ResponseBody
  2. @RequestMapping(value = "/getFilesName",
  3. produces = "text/html;charset=utf-8")
  4. public String getFilesName(HttpServletRequest request,
  5. HttpServletResponse response) throws Exception {
  6. String path = request.getServletContext().
  7. getRealPath("/") + "files/files.json";
  8. String json = JSONFileUtils.readFile(path);
  9. return json;
  10. }

4、编写文件上传和下载页面

(1)创建名称为fileupload.jsp的文件,在fileupload.jsp文件中创建一个文件上传表单,文件上传表单可以发起多文件上传请求。

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>文件上传和下载</title>
  5. <script src="${ pageContext.request.contextPath }/js/jquery-3.6.0.js" type="text/javascript"></script>
  6. </head>
  7. <body>
  8. <table border="1">
  9. <tr>
  10. <td width="200" align="center">文件上传${msg}</td>
  11. <td width="300" align="center">下载列表</td>
  12. </tr>
  13. <tr>
  14. <td height="100">
  15. <form action="${pageContext.request.contextPath}/fileload"
  16. method="post" enctype="multipart/form-data">
  17. <input type="file" name="files" multiple="multiple"><br/>
  18. <input type="reset" value="清空"/>
  19. <input type="submit" value="提交"/>
  20. </form>
  21. </td>
  22. <td id="files"></td>
  23. </tr>
  24. </table>
  25. </body>
  26. </html>

(2)fileupload.jsp加载完成,自动发起异步请求获取文件下载列表并且展示在页面中。

  1. <script>
  2. $(document).ready(function () {
  3. var url = "${pageContext.request.contextPath }/getFilesName";
  4. $.get(url, function (files) {
  5. var files = eval('(' + files + ')');
  6. for (var i = 0; i < files.length; i++) {
  7. $("#files").append("<li>" +
  8. "<a href=${pageContext.request.contextPath }" + "" +
  9. "\\" + "download?filename=" + files[i].name + ">" +
  10. files[i].name + "</a></li>");
  11. }
  12. })
  13. })
  14. </script>

        5、启动chapter13项目,在浏览器中访问fileupload.jsp页面,访问地址为http://localhost:8080/chapter13/fileload.jsp。单击所示的“浏览...”按钮,弹出“文件上传”对话框。

        6、在“文件上传”对话框中,选择需要上传的文件进行上传,在此,选中2个同时上传的文件。 单击所示对话框的右下角“打开”按钮,完成上传文件的选择。完成文件选择之后,“文件上传”对话框自动关闭。

        7、在fileupload.jsp页面显示中,“浏览...”按钮后面显示选择了2个文件。单击“提交”按钮向服务端发送上传请求。左侧栏显示文件上传成功信息,右侧的栏中展示了刚上传成功的文件列表。

三、中文乱码问题

        在实现文件下载的功能时,还需要注意文件中文名称的乱码问题。在使用Content-Disposition设置参数信息时,如果Content-Disposition中设置的文件名称出现中文字符,需要针对不同的浏览器设置不同的编码方式。目前Content-Disposition支持的编码方式有UrlEncode编码、Base64编码、RFC2231编码和ISO编码。本案例不对全部浏览器的编码方式进行设置,只对FireFox浏览器和非FireFox浏览器(如IE)分别进行编码设置。

        8、在文件FileController.java中新增一个方法getFilename(),根据浏览器进行编码设置,并返回编码后的文件名。 新增一个方法fileDownload(),用于下载文件。方法getFilename()的核心代码如下。

  1. /**
  2. * 根据浏览器的不同进行编码设置,返回编码后的文件名
  3. */
  4. public String getFileName(HttpServletRequest request,
  5. String filename) throws Exception {
  6. BASE64Encoder base64Encoder = new BASE64Encoder();
  7. String agent = request.getHeader("User-Agent");
  8. if (agent.contains("Firefox")) {
  9. // 火狐浏览器
  10. filename = "=?UTF-8?B?" + new String
  11. (base64Encoder.encode(filename.getBytes("UTF-8"))) + "?=";
  12. } else {
  13. // IE及其他浏览器
  14. filename = URLEncoder.encode(filename, "UTF-8");
  15. }
  16. return filename;
  17. }

        9、启动chapter13项目,单击步骤7中的fileupload.jsp页面显示效果图所示的“SpringBoot企业级开发教程.png”超链接,弹出下载对话框。可以选择“打开,通过(O)”单选按钮,然后单击对话框的“确定”按钮直接打开下载文件。也可以选择“保存文件(S)”单选按钮,然后单击对话框的“确定”按钮进行下载文件的保存。至此,文件上传和下载案例全部完成。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号