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

一、案例的功能需求

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

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

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

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

        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类的具体代码如下所示。

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的工具类。

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中。

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格式返回数据。

    @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文件中创建一个文件上传表单,文件上传表单可以发起多文件上传请求。

<%@ 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加载完成,自动发起异步请求获取文件下载列表并且展示在页面中。

<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()的核心代码如下。

    /*** 根据浏览器的不同进行编码设置,返回编码后的文件名*/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.mzph.cn/web/48798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

量化交易对多样化投资组合的贡献

量化交易对多样化投资组合的贡献在现代金融市场中尤为显著。通过先进的数学模型和算法&#xff0c;量化交易能够优化投资组合配置&#xff0c;降低风险&#xff0c;提高回报&#xff0c;为投资者提供更稳健的投资策略。在全球经济环境日益复杂的背景下&#xff0c;量化交易成为…

60个常见的 Linux 指令

1.ssh 登录到计算机主机 ssh -p port usernamehostnameusername&#xff1a; 远程计算机上的用户账户名。 hostname&#xff1a; 远程计算机的 IP 地址或主机名。 -p 选项指定端口号。 2.ls 列出目录内容 ls ls -l # 显示详细列表 ls -a # 显示包括隐藏文件在内的所有内…

【GD32】从零开始学GD32单片机 | 基于SD卡的FatFs文件系统移植(GD32F470ZGT6)

1. 简介 FatFs是一个专门为微处理器设计的通用文件系统&#xff0c;像8051、AVR、PIC、ARM架构的微处理器都能兼容该文件系统。 FatFs文件系统最大的一个优点是它是DOS和Windows兼容的&#xff0c;这意味着你只需要再移植一个USB驱动就可以实现在电脑中访问单片机的储存结构&…

Cookie与Session 实现登录操作

Cookie Cookie 是网络编程中使用最广泛的一项技术&#xff0c;主要用于辨识用户身份。 客户端&#xff08;浏览器&#xff09;与网站服务端通讯的过程如下图所示&#xff1a; 从图中看&#xff0c;服务端既要返回 Cookie 给客户端&#xff0c;也要读取客户端提交的 Cookie。所…

Domainim:一款高效的企业级网络安全扫描工具

关于Domainim Domainim是一款功能强大的企业级网络安全扫描工具&#xff0c;该工具运行效率高&#xff0c;功能完善&#xff0c;可以帮助广大研究人员针对企业或组织网络执行大规模安全扫描任务。 该工具可以快速执行网络安全扫描和域名/子域名网络侦查任务&#xff0c;旨在使…

CCF GESP Python编程 五级认证真题 2024年6月

第 1 题 在Python中&#xff0c;print((c for c in "GESP"))的输出是&#xff08; &#xff09;。 A.(G, E, S, P) B.[G, E, S, P] C.{G, E, S, P} D. 以上选项均不正确 第 2 题 下面有关快速排序的说法&#xff0c;错误的是&#xff08; …

python毕业设计选题协同过滤算法在音乐推荐系统

✌网站介绍&#xff1a;✌10年项目辅导经验、专注于计算机技术领域学生项目实战辅导。 ✌服务范围&#xff1a;Java(SpringBoo/SSM)、Python、PHP、Nodejs、爬虫、数据可视化、小程序、安卓app、大数据等设计与开发。 ✌服务内容&#xff1a;免费功能设计、免费提供开题答辩P…

暑期C++ 缺省参数

有任何不懂的问题可以评论区留言&#xff0c;能力范围内都会一一回答 1.缺省参数的概念 缺省参数是是声明或定义参数时为函数的参数指定一个缺省值。在调用该函数值时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参 看了上面定义后&#…

【零基础必看的前端教程】——JavaScript(七)数组

欢迎大家打开前端的新篇章——JavaScript&#xff0c;JavaScript与HTML、CSS合称为前端三大件&#xff0c;JavaScript是前端的重中之重&#xff0c;小洪将继续以零基础视角&#xff0c;带你循序渐进学习前端知识&#xff0c;一看就懂&#xff0c;小白也能转行做前端&#xff01…

vue3实现在新标签中打开指定的网址

有一个文件列表&#xff0c;如下图&#xff1a; 我希望点击查看按钮的时候&#xff0c;能够在新的标签页面打开这个文件的地址进行预览&#xff0c;该如何实现呢&#xff1f; 比如&#xff1a; 实际上要实现这个并不难&#xff0c;参考demo如下&#xff1a; 首先&#x…

求职学习day10

总结&#xff1a; 抽空做面试前模拟和拷打八股模拟 面试鸭刷题神器 (mianshiya.com) 贪吃的猴子&#xff0c;滑动窗口&#xff0c;反向思考问题。将左右获取数组转变成中间连续的数组窗口。 滑动窗口3问 左指针什么时候右移&#xff0c;有什么操作右指针什么时候右移&am…

QWidget如何切换ui

在Qt中&#xff0c;QWidget及其子类用于构建图形用户界面。如果你想要在不同的UI之间切换&#xff0c;可以使用QStackedWidget&#xff0c;它可以管理一组QWidget&#xff0c;并且每次只显示其中一个。 以下是一个简单的例子&#xff0c;展示如何使用QStackedWidget切换UI&…

渗透测试——利用公网反弹shell到本地的两种方式,vmware虚拟机与主机的端口转发,本地ssh无法上线的问题解决

解决问题&#xff1a; 因长期使用本地模拟靶场&#xff0c;实战护网时并非模拟靶场&#xff0c;shell反弹需要利用公网测试。解决目标站无法反弹到本地的情况。解决本地是windows&#xff0c;虚拟机是kail、linux&#xff0c;无法相互转换流量的情况。 环境搭建 靶机 centOS7 …

CentOS7系统安装CMake3.6.2

文章目录 前言一、下载CMake二、拷贝CMake三、解压CMake四、重命名五、编译及安装六、系统文件中增加变量七、查看CMake版本 前言 CentOS7系统如何安装CMake3.6.2?本文记录其安装过程。 一、下载CMake wget https://cmake.org/files/v3.6/cmake-3.6.2.tar.gz二、拷贝CMake …

Android 12系统源码_窗口动画(二)应用程序间的切换动画

前言 在 Android 系统中&#xff0c;系统主要是通过AppTransitionController和AppTransition这两个类是用于管理应用程序间切换动画的重要类。 一、简介 1、AppTransitionController AppTransitionController 是一个系统级别的类&#xff0c;用于管理应用程序间切换时的动画…

《简历宝典》20 - 简历中“自我评价”,如何能够“画龙点睛”

前两节我们针对 “项目经历” 和 “技术能力” 模块做了内功与实战的讲解&#xff0c;可以说是重中之重&#xff0c;是简历优化新思路的核心所在。这一节开始对自我评价做讲解&#xff0c;自我评价一般都会放置在简历的末尾&#xff0c;HR在迅速浏览完个人信息、技术能力、学历…

VScode 批量操作

VScode 批量操作 批量修改 按住 alt/option 键&#xff0c; 选择需要批量操作的位置 如果是多行&#xff0c;则按住 altshift 键 可以直接操作 但是有时候比如变量命名&#xff0c;可能需要递增操作的命名 需要下载插件 Increment Selection 按照1的方法多选光标之后&am…

后端面试题日常练-day04 【Java基础】

题目 希望这些选择题能够帮助您进行后端面试的准备&#xff0c;答案在文末 在Java中&#xff0c;以下哪个关键字用于表示接口&#xff1f; a) interface b) implements c) extends d) interfaceOf Java中的静态变量有什么特点&#xff1f; a) 静态变量属于对象实例 b) 静态变…

html+css+js前端作业 王者荣耀官网5个页面带js

htmlcssjs前端作业 王者荣耀官网5个页面带js 下载地址 https://download.csdn.net/download/qq_42431718/89574989 目录1 目录2 目录3 项目视频 王者荣耀5个页面&#xff08;带js&#xff09; 页面1 页面2 页面3 页面4 页面5

php接口返回的json字符串,json_decode()失败,原来是多了红点

问题&#xff1a; 调用某个接口返回的json&#xff0c;json_decode()失败&#xff0c;返回数据为null&#xff0c; echo json_last_error();返回错误码 4 经过多次调试发现&#xff1a;多出来一个红点&#xff0c;预览是看不到的。 解决&#xff1a;要去除BOM头部 $resul…