JavaEE简单示例——文件的上传和下载
文件的上传和下载的实现原理的简单介绍
表单的构成
首先,我们先来介绍我们的需要用到的表单,在这个表单中,首先值得我们注意的就是,在type为file的input标签中.这个控件是我们主要用来选择上传的文件的, 除此之外,我们要想实现文件的上传,还需要将method的属性的值设置为post,只有当请求方式为post的时候才能携带数据.以及enctype属性的值设置为multipart/form-data, 表示告诉浏览器以流的方式来处理我们的数据,这样在后台才能进行解析. 简单来说,在页面中,要想实现文件的上传需要进行必要的三个设置:
- 将input标签的type属性设置为file
- 将form标签的method的属性的值设置为post
- 将form标签的enctype属性的值设置为multipart/form-data
还有一点就是在H5之后,出现了一个新的属性叫做multiple,这个属性用在文件上传框中,可以一次上传多个文件.
然后,就是用来展示已经上传的文件的列表 列表的实现非常的简答,我们只只需要在页面加载的时候向后台发送一个请求,向负责文件读取的控制器请求一下文件列表,然后将获取的文件列表追加到表格中, 这个文件的编写比较重要的就是from属性的配置,以及在追加文件列表的时候注意标签和变量的拼接
页面代码:
<%--Created by IntelliJ IDEA.User: 33680Date: 2023/3/29Time: 8:25To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head><title>文件的上传和下载</title><script src="${pageContext.request.contextPath}/js/jquery-3.6.4.min.js"type="text/javascript"></script><style>table{border: 2px solid black;}td{border: 1px solid black;}</style>
</head>
<body>
<form action="${pageContext.request.contextPath}/fileUplode" method="post" enctype="multipart/form-data"><table><tr><td width="200" align="center">文件上传${msg}</td><td width="200" align="center">下载列表</td></tr><tr><td><input type="file" name="files" multiple="multiple"><input type="reset" value="清空"><input type="submit" value="提交"></td><td id="files"></td></tr></table>
</form>
<script>$(document).ready(function (){var url = "${pageContext.request.contextPath}/getFileName";$.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>
</body>
</html>
文件上传
在文件的上传这部分,首先我们需要获取文件的列表,所以我们需要使用SpringMVC的MultipartFile类来封装,要使用这个类,我们首先需要在配置文件中配置多部件解析器
多部件解析器
多部件解析器就是一个JavaBean,所以我们需要在spring-mvc.xml文件中进行配置,需要注意的是,这个JavaBean的id的值是固定的,所以我们在配置的时候需要注意 然后我们就可以配置其他属性了,我们使用依赖注入的方式向里面注入配置参数:
- defaultEncoding:这个属性是配置请求的编码格式,一般为UTF-8
- maxUploadSize:这个属性是限制上上传的文件的大小,单位是字节
在配置完成多部件解析器之后,我们就可以顺利的使用SpringMVC的MultipartFile类来处理上传的文件了. 对于这个类的使用,我们使用最频繁的方法主要有两个:
- isEmpty():这个方法用来判断上传的文件是否为空
- transferTo(File file):这个方法的功能是保存文件
文件上传的基本流程是:首先,我们从页面中上传文件到后台,然后后台使用MultipartFile类来封装文件,如果文件不为空,则将其使用transferTo()方法保存到我们设置的路径中.
在上传文件时对重名文件的处理
在我们上传文件的时候,可能会遇到重名的文件,对于重名的文件,我们要做一些设置改变他原有的名字.首先,我们要创建一个文件叫做files.json文件这个文件的作用是存放我们的文件名字. 在我们保存文件之前,我们要先读取这个文件,对于这个文件的读写操作,我们都封装进了一个工具类中,可以方便我们对文件信息类的操作, 之后,判断读取到的文件内容,如果内容为空,则表示是第一个文件,直接保存.如果文件中有内容,我们就将数据信息文件中的内容读取出来,并且封装进一个类中,更加方便我们在Java中操作这个数据信息. 然后我们会判断文件名是否重名,如果重名了,则将原来的文件名以"."进行分割,然后在中间拼接上一个"(1)",变成一个新的文件名进行保存.
文件下载
对于文件的下载就比较简单了,基本的格式都是固定的
- 首先我们设置被下载的文件所在的文件夹的路径
- 一般,我们要下载文件的时候会携带一个下载文件的请求,我们就可以使用文件夹路径和请求中携带的文件名参数拼接成唯一的文件路径,然后通过文件路径创建文件对象
- 创建响应头对象,然后设置响应头,告诉浏览器我要对文件进行下载,并且以流的形式处理文件
- 最后,我们使用Spring的ResponseEntity类对下载的文件进行处理操作,直接返回ResponseEntity类的对象,流处理的文件,响应头对象和响应状态码
文件名的的编码转换
我们接收到的文件的编码可能会导致出错,所以我们可能需要对文件名进行转码,转码的方式也很简单:
- 首先我们要判断发送请求的浏览器是否为火狐,如果是火狐我们需要按照火狐的方式修改编码
- 然后就是判断如果不是火狐,则直接使用普通的方式修改文件编码即可
文件列表的展示
在之前我们上传文件的时候,我们会将上传的文件的文件名写入到一个json文件中,一个是用来判断文件是否重名,另一个作用是我们可以读取里面的信息, 传递到页面中形成一个列表,让我们的对文件有一个更直观的了解. 对于列表的展示,我们只需要获取json文件的路径,然后使用我们之前创建的JSON文件读取写入工具类,将我们的JSON文件的内容读取到页面中,然后在页面中对读取的数据进行处理之后展示出来即可
JSON文件操作工具类:
package SpringMVC.Upload_and_download.utils;
//这个包是在之前我们学过的方便我们对文件的读写操作的类
import org.apache.commons.io.IOUtils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;//这个类的作用是方便我们对JSON文件的读取操作
public class JSONFileUtils {
// 读取文件中的内容public static String readFile(String filepath) throws IOException {
// 根据传递进来的参数,创建文件输出流,将文件中的内容输出获取出来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);}
}
JSON文件映射类:
package SpringMVC.Upload_and_download;
//这个类的作用是为了方便Json内容的读取,我们创建与Json内容对应的实体类方便我们在Java代码中的操作
public class Resource {private String name;@Overridepublic String toString() {return "Resource{" +"name='" + name + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public Resource(String name) {this.name = name;}public Resource() {}
}
文件上传下载控制器:
package SpringMVC.Upload_and_download.utils;import SpringMVC.Upload_and_download.Resource;
import com.fasterxml.jackson.databind.ObjectMapper;
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 com.fasterxml.jackson.core.type.TypeReference;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;//这个类的作用是实现文件的上传和下载
@Controller
public class FileController {/**** @param files 保存上传的多个文件列表* @param request 当前请求的信息* @return 返回的是响应的页面,以请求转发的方式* @throws Exception 抛出多个异常,直接抛出最大的异常*/
// 文件的上传@RequestMapping("/fileUplode")public String fileUplode(MultipartFile[] files , HttpServletRequest request) throws Exception {
//存放文件存放的路径String path = request.getServletContext().getRealPath("/") + "files/";
// 创建JSON转换类的对象ObjectMapper om = new ObjectMapper();
// 判断上传的文件是否为空if(files!=null && files.length>0){
// 如果文件列表不为空,并且长度大于零,则表示有文件上传,正常进行处理for(MultipartFile file : files){//首先获取上传文件的文件名,创建一个列表存放文件信息
// getOriginalFilename()方法是用来获取上传时的文件名String filename = file.getOriginalFilename();List<Resource> list = new ArrayList<>();
// 读取文件files.json文件中的数据,判断上传的文件名是否重名String json = JSONFileUtils.readFile(path+"/files.json");
// 先判断JSON文件中是否有数据,如果没有数据就表示这是第一个上传的文件,肯定不会重名System.out.println(json.length());if(json.length()!=0){
// 将JSON文件中的数据转换成集合,方便我们的判断操作list = om.readValue(json, new TypeReference<List<Resource>>() {});for(Resource resource : list){
// 进行判断if (filename != null && filename.equals(resource.getName())) {String []strings = filename.split("\\.");filename = strings[0]+"(1)."+strings[1];System.out.println(filename);}}}
// 文件保存的完整路径String Filepath = path+filename;
// 开始保存文件file.transferTo(new File(Filepath));list.add(new Resource(filename));
// 将集合中的数据转换成jsonjson = om.writeValueAsString(list);
// 将上传的文件名称保存在file.json中JSONFileUtils.writeFile(json,path+"/files.json");System.out.println(json);System.out.println(list.toString());}
// 将文件的上传状态传递到页面中request.setAttribute("msg","上传成功");return "forward:/SpringMVC/pages/FIle.jsp";}
// 当我们没有进入第一个if时,则表示所有的状态都是失败状态,所以我们此处返回失败的状态信息request.setAttribute("msg","上传失败");return "forward:/SpringMVC/pages/FIle.jsp";}// 实现文件列表的功能@ResponseBody@RequestMapping(value = "/getFileName" , produces = "text/html;charset=utf-8")public String getFileName(HttpServletRequest request) throws IOException {
// 获取项目的路径String path = request.getServletContext().getRealPath("/")+"files/files.json";return JSONFileUtils.readFile(path);}// 在实现文件下载之前,我们需要先去实现一个解决文件乱码的问题public String getFileName(HttpServletRequest request,String filename)throws Exception{
// 由于各浏览器支持的编码格式转换的方式不一样,主要体现在火狐浏览器的配置不一样,所以这里需要获取请求头中携带的浏览器型号是不是火狐BASE64Encoder base64Encoder = new BASE64Encoder();String agent = request.getHeader("User-Agent");if(agent.equals("Firefox")){
// 如果是火狐,则需要使用火狐规则的浏览器转码格式filename = "=?UTF-8?B?"+ base64Encoder.encode(filename.getBytes(StandardCharsets.UTF_8)) +"?=";}else {
// 其他的就使用统一的转码方式filename = URLEncoder.encode(filename,"UTF-8");}
// 最后将转码之后的文件名返回即可return filename;}// 实现文件的下载@RequestMapping("/download")public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename)throws Exception{
// 需要下载的文件的根路径String path = request.getServletContext().getRealPath("/files/");
// filename = new String(filename.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
// 根据传递进来的数据不同下载不同的文件File file = new File(path+File.separator+filename);
// 创建设置响应头的对象HttpHeaders headers = new HttpHeaders();
// 将文件名进行转码处理filename = this.getFileName(request,filename);
// 告诉浏览器我要对这个文件进行下载处理headers.setContentDispositionFormData("attachment",filename);
// 以流的形式处理文件headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 最后返回读取到的文件,在浏览器中就可以显示为下载
// 使用SpringMVC的ResponseEntity处理封装的数据return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);}
}
文件目录结构:
注意点
对于文件的上传和下载,我们主要知道大概的流程,和我们需要做的事情即可,可以看到大部分的流程都是固定的,并且大部分都是工具类的使用,所以我们如果实在记不住具体的操作可以随时来复制就可以.
相关文章:

JavaEE简单示例——文件的上传和下载
文件的上传和下载的实现原理的简单介绍 表单的构成 首先,我们先来介绍我们的需要用到的表单,在这个表单中,首先值得我们注意的就是,在type为file的input标签中.这个控件是我们主要用来选择上传的文件的, 除此之外,我们要想实现文件的上传,还需要将method的属性的值设置为post…...

【C语言督学训练营 第五天】数组字符串相关知识
文章目录前言一、数组的定义1.一维数组①.如何定义②.声明规则③.内存分布④.初始化方法2.二维数组3.高维数组二、访问数组元素相关问题1.访问越界2.数组的传递三、Scanf与字符数组1.字符数组初始化2.scanf读取字符四、字符数组相关函数前言 今天的C语言训练营没有安排高维数组…...

GPT-4 免费体验方法
POE 在Quora上非常受欢迎的手机聊天机器人Poe App已经集成ChatGPT助手!除了最初集成的三个聊天机器人Sage、Claude和Dragonfly外,Poe现在还加入了第四位ChatGPT。由于使用了ChatGPT API,因此Poe拥有真正的ChatGPT。 现在更是第一批集成了GP…...
中断-屏蔽位
1.中断控制器(PIC:适用于单处理器、APIC) 1.定义 中断控制器可以看作是中断服务的代理,外设五花八门,如果没有一个中断的代理,外设想要给cpu发送中断信号来处理中断。那么只能是外设连接在cpu引脚上,由于cpu引脚很宝贵,所以不可能拿出那么多引脚来供外设连接,所以就有…...
【洛谷P1636】 Einstein学画画
题目描述:Einstein 学起了画画。此人比较懒~~,他希望用最少的笔画画出一张画……给定一个无向图,包含 n 个顶点(编号 1∼n),m 条边,求最少用多少笔可以画出图中所有的边。输入格式第一行两个整数…...
户外LED显示屏钢结构制作原则
户外LED显示屏在施工安装时是必须要制作固定钢结构的,因为户外LED显示屏工作环境相对比较恶劣,制作钢结构一是为了安全,二是为了提高防护等级。那么户外LED显示屏钢结构制作原则是什么呢?迈普光彩小编总结了一些分享个大家。 户外…...
【内网穿透】使用Haproxy反向代理搭建企业私有云:神卓互联教程
神卓互联是一款强大的内网穿透工具,可以帮助企业搭建私有云,实现对内部资源的远程访问。在搭建私有云的过程中,使用HAProxy反向代理可以提高系统的性能和可靠性。本文将介绍如何使用神卓互联和HAProxy反向代理搭建私有云。 步骤如下…...
spring boot项目:实现与数据库的连接
步骤【写在前面】定义数据库连接信息:引入数据库驱动:创建数据源:创建JdbcTemplate:编写DAO层:使用Service注解标注Service层:使用RestController注解标注Controller层:示例代码:app…...

【gitlab部署】centos8安装gitlab(搭建属于自己的代码服务器)
这里写目录标题部署篇序言要求检查系统是否安装OpenSSH防火墙问题准备gitlab.rb 配置坑点一忘记root密码重置使用篇gitlab转换成中文git关闭注册入口创建用户部署篇 序言 在团队开发过程中,想要拥有高效的开发效率,选择一个好的代码开发工具是必不可少的…...
2021年全国职业院校技能大赛(中职组)网络安全竞赛第三套试题A模块解析(超级详细)
2021年全国职业院校技能大赛(中职组) 网络安全竞赛试题 (3) (总分100分) 赛题说明 一、竞赛项目简介 “网络安全”竞赛共分A. 基础设施设置与安全加固;B. 网络安全事件响应、数字取证调查和应用安全;C. CTF夺旗-攻击;D. CTF夺旗-防御等四个模块。根据比赛实际情况…...

Hbase异步复制和同步复制解析
背景 Hbase是一个KV数据库,自然和Mysql以及Redis等会涉及到复制的问题,也有主从集群的概念,那么本文就来看下Hbase的复制逻辑 Hbase复制实现 首先我们先在回顾下,在Hbase实现中,每个RegionServer上面会包含多个Regi…...

TIKTOK海外直播公会如何申
在“清朗行动”的规范化整治下,国内秀场直播俨然成为了“夕阳行业”,早已度过了野蛮生长的阶段。随着直播公会内卷竞争加剧,公会的生存也愈发艰难,有的娱乐主播甚至纷纷转行做起了电商,可见国内娱乐直播行业的惨淡。 …...

6.springcloud微服务架构搭建 之 《springboot集成Gateway》
5.springcloud微服务架构搭建 之 《springboot集成Hystrix》 目录 1.gateway介绍 2.项目引入gateway 3.yml配置gateway参数 5.自定义全局Filter 6.测试 1.gateway介绍 服务网关(Spring Cloud Gateway)是Spring Cloud官方推出的 第二代网关框架&#…...

[N1CTF 2018]eating_cms_
目录 信息收集 代码审计 parse_url解析漏洞 信息收集 进入即是登录页面,抓包一看应该是SQL注入,但是空格、%、|等等啥的都被waf了,不太好注入,先信息收集一波 花一分钟扫下目录,发现一个viminfo和register.php Viminfo文件…...

《Spring系列》第13章 Aop切面(二) 代理创建
前言 本篇文章主要介绍AOP的源码,要想看懂AOP,那么就看AOP给容器中注入了什么组件,这个组件什么时候工作,这个组件的功能是什么? EnableAspectJAutoProxy会向IOC容器中注入一个后置处理器,它会在Bean的创…...
算法-贪心
贪心算法1信息学竞赛课堂贪心算法2贪心法实际生活中,经常需要求一些问题的“可行解”和“最优解”,这就是所谓的“最优化”问题。一般来说,每个最优化问题都包含一组“限制条件”和一个“目标函数”,符合限制条件的问题求解方案称…...

【数据结构与算法】树(Tree)【详解】
文章目录前言树一、树的基本概念1、树的定义2、基本术语3、树的性质二、树的存储结构1、双亲表示法2、孩子表示法3、孩子兄弟表示法二叉树一、二叉树的概念1、二叉树的定义2、几个特殊的二叉树3、二叉树的性质4、二叉树的存储结构二、遍历二叉树1、先序遍历2、中序遍历3、后序遍…...

OSPF------LSA 详解
LSA头部 [r1]display ospf lsdb 链路状态老化时间(Link-State Age) 16bits,单位s当该LSA被始发路由器产生时,该值被设置为0,之后随着该LSA在网络中被洪泛,老化时间逐渐累积。(但是不能让它一直增长&#x…...
js加解密入门
首先,让我们简单介绍一下百度公司的文心一言。文心一言是百度公司推出的一项文本生成工具,它可以根据给定的主题或关键词生成一句简短而富有启发性的文字。在我们的加密和解密方法中,我们将利用文心一言的特点来生成随机的字符串,…...

vue+Echarts导入自定义地图
在vue项目先安装echarts //在vue文件中的<script>中引入 import * as echarts from "echarts"; import geoJson from ../assets/map/Fmap.json; //自定义地图的位置 import * as topojson from "topojson-client"; //使用组件topojson-client自定…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...