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

devtools/2024/10/18 14:18:33/

一、案例的功能需求

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

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

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

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

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

<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version>
</dependency>

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

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

2、实现文件上传功能

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

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

java">public class Resource {private String name;                //name属性表示文件名称public Resource() {}public Resource(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

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

java">import org.apache.commons.io.IOUtils;import java.io.FileInputStream;
import java.io.FileOutputStream;public class JSONFileUtils {public static String readFile(String filepath) throws Exception {FileInputStream fis = new FileInputStream(filepath);return IOUtils.toString(fis);}public static void writeFile(String data, String filepath)throws Exception {FileOutputStream fos = new FileOutputStream(filepath);IOUtils.write(data, fos);}
}

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

java">import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.pojo.Resource;
import com.itheima.utils.JSONFileUtils;
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.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;@Controller
public class FileController {/*** 文件上传*/@RequestMapping("fileload")public String fileLoad(MultipartFile[] files,HttpServletRequest request) throws Exception {//设置上传的文件所存放的路径String path = request.getServletContext().getRealPath("/") + "files/";ObjectMapper mapper = new ObjectMapper();if (files != null && files.length > 0) {//循环获取上传的文件for (MultipartFile file : files) {//获取上传文件的名称String filename = file.getOriginalFilename();ArrayList<Resource> list = new ArrayList<>();//读取files.json文件中的文件名称String json = JSONFileUtils.readFile(path + "/files.json");if (json.length() != 0) {//将files.json的内容转为集合list = mapper.readValue(json,new TypeReference<List<Resource>>() {});for (Resource resource : list) {//如果上传的文件在files.json文件中有同名文件,将当前上传的文件重命名,以避免重名if (filename.equals(resource.getName())) {String[] split = filename.split("\\.");filename = split[0] + "(1)." + split[1];}}}// 文件保存的全路径String filePath = path + filename;// 保存上传的文件file.transferTo(new File(filePath));list.add(new Resource(filename));json = mapper.writeValueAsString(list); //将集合中转换成json//将上传文件的名称保存在files.json文件中JSONFileUtils.writeFile(json, path + "/files.json");}request.setAttribute("msg", "(上传成功)");return "forward:fileload.jsp";}request.setAttribute("msg", "(上传失败)");return "forward:fileload.jsp";}
}

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

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

java">    @ResponseBody@RequestMapping(value = "/getFilesName",produces = "text/html;charset=utf-8")public String getFilesName(HttpServletRequest request,HttpServletResponse response) throws Exception {String path = request.getServletContext().getRealPath("/") + "files/files.json";String json = JSONFileUtils.readFile(path);return json;}

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

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

javascript"><%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>文件上传和下载</title><script src="${ pageContext.request.contextPath }/js/jquery-3.6.0.js" type="text/javascript"></script>
</head>
<body>
<table border="1"><tr><td width="200" align="center">文件上传${msg}</td><td width="300" align="center">下载列表</td></tr><tr><td height="100"><form action="${pageContext.request.contextPath}/fileload"method="post" enctype="multipart/form-data"><input type="file" name="files" multiple="multiple"><br/><input type="reset" value="清空"/><input type="submit" value="提交"/></form></td><td id="files"></td></tr>
</table>
</body>
</html>

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

javascript"><script>$(document).ready(function () {var url = "${pageContext.request.contextPath }/getFilesName";$.get(url, function (files) {var files = eval('(' + files + ')');for (var i = 0; i < files.length; i++) {$("#files").append("<li>" +"<a href=${pageContext.request.contextPath }" + "" +"\\" + "download?filename=" + files[i].name + ">" +files[i].name + "</a></li>");}})})
</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()的核心代码如下。

java">    /*** 根据浏览器的不同进行编码设置,返回编码后的文件名*/public String getFileName(HttpServletRequest request,String filename) throws Exception {BASE64Encoder base64Encoder = new BASE64Encoder();String agent = request.getHeader("User-Agent");if (agent.contains("Firefox")) {// 火狐浏览器filename = "=?UTF-8?B?" + new String(base64Encoder.encode(filename.getBytes("UTF-8"))) + "?=";} else {// IE及其他浏览器filename = URLEncoder.encode(filename, "UTF-8");}return filename;}

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


http://www.ppmy.cn/devtools/86007.html

相关文章

Godot入门 02玩家1.0版

添加Node2D节点&#xff0c;重命名Game 创建玩家场景&#xff0c;添加CharacterBody2D节点 添加AnimatedSprite2D节点 从精灵表中添加帧 选择文件 设置成8*8 图片边缘模糊改为清晰 设置加载后自动播放&#xff0c;动画循环 。动画速度10FPS&#xff0c;修改动画名称idle。 拖动…

Laravel为什么会成为最优雅的PHP框架?

Laravel 成为最优雅的 PHP 框架的原因可以从多个方面来解释。以下是一些关键因素&#xff1a; 简洁优雅的语法: Laravel 采用了简洁明了的语法&#xff0c;使得代码更容易阅读和编写。它支持现代 PHP 特性&#xff0c;如命名空间、类自动加载、匿名函数&#xff08;闭包&#x…

力扣面试题(一)

1、给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就将多出来的字母追加到合并后字符串的末尾。 char * mergeAlternately(char * word1, char * word2){int len1 strlen(word1);i…

C++ //练习 15.28 定义一个存放Quote对象的vector,将Bulk_quote对象传入其中。计算vector中所有元素总的net_price。

C Primer&#xff08;第5版&#xff09; 练习 15.28 练习 15.28 定义一个存放Quote对象的vector&#xff0c;将Bulk_quote对象传入其中。计算vector中所有元素总的net_price。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块&am…

ClkLog:开源用户行为分析框架,让数据分析更轻松

ClkLog&#xff1a;开源用户行为分析框架&#xff0c;让数据分析更轻松 在数据驱动的时代&#xff0c;找到一个好用的用户行为分析工具真是难上加难。但是今天你有福了&#xff0c;开源免费的 ClkLog 就是你的不二选择&#xff01;本文将为你详细介绍 ClkLog 的功能特点、技术架…

Python内存管理:引用计数与垃圾回收

✨ 内容&#xff1a; 在Python中&#xff0c;内存管理是一个重要且常常被忽视的话题。了解Python如何管理内存&#xff0c;不仅能帮助我们编写高效的代码&#xff0c;还能避免潜在的内存泄漏问题。今天&#xff0c;我们将通过一个实际案例&#xff0c;深入探讨Python的内存管理…

如何正确看待《劳动论》与经济的关系?

《劳动论》与经济的关系是一个深刻且复杂的议题&#xff0c;全面探讨了劳动在经济理论中的核心地位、所起的作用以及劳动与经济发展之间的动态互动关系。 劳动被视为经济理论的基石&#xff0c;这体现在两个方面&#xff1a;一是劳动创造价值&#xff0c;它是财富创造的源泉&a…

嵌入式C++、STM32、Flask框架、SQL、ROS系统和MQTT协议通讯:智能药盒及物联网数据监测设计思路(代码示例)

目录 项目概述 系统设计 硬件设计 软件设计 系统架构图 代码实现 1. 开发环境 2. STM32 微控制器代码示例 3. ROS 节点代码示例 4. 后端服务器代码示例&#xff08;Flask&#xff09; 数据库部分 3.4 删除药物记录 项目概述 随着老龄化社会的加剧&#xff0c;患者…