springboot简单集成上传和下载(带页面)

news2024/12/24 20:52:00

来学习一下文件上传和下载


一、页面开发

整体思路

登录页

主页


二、库表设计

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_files
-- ----------------------------
DROP TABLE IF EXISTS `t_files`;
CREATE TABLE `t_files` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `oldFileName` varchar(255) DEFAULT NULL,
  `newFileName` varchar(255) DEFAULT NULL,
  `ext` varchar(255) DEFAULT NULL,
  `path` varchar(255) DEFAULT NULL,
  `size` varchar(255) DEFAULT NULL,
  `type` varchar(255) DEFAULT NULL,
  `isImg` int(11) NOT NULL,
  `downCounts` varchar(255) DEFAULT NULL,
  `uploadTime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of t_files
-- ----------------------------

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of t_user
-- ----------------------------

三、环境搭建


四、用户登录开发

这次新建了一个工程,因为 Lombok 用得很习惯,但以前的话,一般只用了@Data@AllArgsConstructor@EqualsAndHashCode等常规注解;那这个Accessors(chain = true)注解是干嘛的呢?

https://www.cnblogs.com/grey-wolf/p/11812528.html

五、用户文件列表

        <tr th:each="f:${file}">
            <td th:text="${f.id}"></td>
            <td th:text="${f.oldFileName}"></td>
            <td th:text="${f.newFileName}"></td>
            <td th:text="${f.ext}"></td>
            <td th:text="${f.path}"></td>
            <td th:text="${f.size}"></td>
            <td th:text="${f.type}"></td>
            <td th:text="${f.isImg}"></td>
            <td th:text="${f.downCounts}"></td>
            <td th:text="${#dates.format(f.uploadTime,'yyyy-MM-dd')}"></td>//日期格式化
            <td><a href="">下载</a>&nbsp;<a href="">在线打开</a>&nbsp;<a href="">删除</a></td>
        </tr>

六、用户文件上传

1、文件上传

记录旧文件名、新文件名、文件后缀、文件大小、文件路径、文件类型、下载次数、下载时间、是否图片

    /**
     * 上传文件并保存到数据库中
     * 文件名lujiahong要和表单中的name属性一一对应
     * 上传的文件存在static里面
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("lujiahong") MultipartFile file,HttpSession session) throws IOException {
        //1、获取文件原始名称
        String oldFileName = file.getOriginalFilename();
        //2、按旧文件名获取文件后缀(创建新文件名名获取文件后缀 ,需要引入依赖包commons-fileupload)
        String extension ="."+ FilenameUtils.getExtension(oldFileName);
        //3、生成新的文件名称(当前时间+UUID+后缀)——UUID里面有符号"-",替换为""
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date() )+ UUID.randomUUID().toString().replace("-","")+extension;
        //4、文件大小
        Long size = file.getSize();
        //5、文件类型
        String type = file.getContentType();
        //6、根据日期生成目录
            //通过工具类ResourceUtils去获取静态文件下指定文件的真实路径
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "/static/files";
            //生成动态日期路径
        String dataFormat = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dateDirPath = realPath + "/" + dataFormat;
            //得到日期目录
        File dateDir = new File(dateDirPath);
        if(!dateDir.exists()) {
            dateDir.mkdirs();
        }
        //7、处理文件上传
        file.transferTo(new File(dateDir,newFileName));
        //8、文件相关数据存入数据库
        Files files = new Files();
        files.setUserId(((User)session.getAttribute("user")).getId());
        files.setOldFileName(oldFileName);
        files.setNewFileName(newFileName);
        files.setExt(extension);
        files.setType(type);
        files.setSize(size);
        files.setPath("/files/"+dataFormat);
        files.setDownCounts("0");
        files.setUploadTime(new Date());
        files.setIsImg(0);
        this.iFilesService.save(files);
        return "redirect:/file/showAll";
    }

2、配置文件上传大小、以及一次性可上传文件大小

    spring: 
      servlet:
        multipart:
        max-file-size: 50MB #设置单个文件大小
        max-request-size: 50MB #设置单次请求文件的总大小
@Configuration
public class MultipartConfig {
    @Bean
    public MultipartConfigElement multipartConfigElement(){
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.parse("50MB"));//允许上传的文件最大值
        factory.setMaxRequestSize(DataSize.parse("50MB"));// 设置总上传数据总大小
        return factory.createMultipartConfig();
    }
}

3、参考

  1. 参考一
  2. 参考二
  3. 参考三

七、用户上传文件是否是图片判断

1、后台响应前台

public class ResBack {
    public static void response(String msg, HttpServletResponse response){
        try {
            response.setContentType("text/html; charset=UTF-8"); //转码
            PrintWriter out = response.getWriter();
            out.flush();
            out.println("<script>");
            out.println("alert('"+msg+"');");
            out.println("history.back();");
            out.println("</script>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2、后台在线播放

servletContext.contextPath用来获取文件项目中的地址,后面是保存在项目static里面的路径的拼接

            <td th:switch="${f.isImg ne ''}">
                <img th:case="${f.isImg eq '图片'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" style="width: 100px;height: 100px">
                <video th:case="${f.isImg eq '视频'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" controls="controls" style="width: 100px;height: 100px"></video>
                <audio th:case="${f.isImg eq '音频'}" th:src="${#servletContext.contextPath+f.path+'/'+f.newFileName}" controls="controls" style="width: 100px;height: 100px"></audio>
                <p th:case="${f.isImg eq '未知类型'}">未知类型</p>
            </td>


八、用户下载文件

    @GetMapping("/download")
    public void down(@RequestParam("id") int id,HttpServletResponse response) throws IOException {
        //1、获取文件信息
        Files files = this.iFilesService.getById(id);
        //2、更新下载次数
        files.setDownCounts(files.getDownCounts()+1);
        this.iFilesService.updateById(files);
        //2、根据文件存储路径path和文件名获取文件输出流
        String downPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + files.getPath();
        //3、获取文件输入流
        FileInputStream fileInputStream = new FileInputStream(new File(downPath,files.getNewFileName()));
        //4、附件格式下载设置头部( URLEncoder.encode(files.getOldFileName(),"utf-8") 设置文件名编码风格,避免乱码)
        response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(files.getOldFileName(),"utf-8"));
        //4、获取响应输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //5、文件拷贝
        IOUtils.copy(fileInputStream,outputStream);
        //6、关闭输入输出流
        IOUtils.closeQuietly(fileInputStream);
        IOUtils.closeQuietly(outputStream);
    }

九、用户删除文件

1、前台请求url的写法——thymeleaf

@{/file/download(id=${f.id},openStyle=‘inline’)}相当于file/download?id=30&openStyle=inline

<a th:href="@{/file/download(id=${f.id})}" target="_blank">下载</a>&nbsp;
<a th:href="@{/file/download(id=${f.id},openStyle='inline')}" target="_blank">在线打开</a>
<a th:href="@{/file/delFile(id=${f.id})}">删除</a><

2、在线展示数据

下载还是在线打开(逻辑判断,设置不同请求头即可实现;attachment——下载;inline——在线打开)

response.setHeader(“content-disposition”,“attachment;fileName=文件名”);//下载头部设置

response.setHeader(“content-disposition”,“inline;fileName=文件名”);//预览头部设置

    @GetMapping("/download")
    public void down(String openStyle,@RequestParam("id") int id,HttpServletResponse response) throws IOException {
        //获取打开方式——下载还是在线打开(共用一个接口,逻辑判断,设置不同请求头即可实现;attachment——下载;inline——在线打开)
        openStyle = openStyle == null? "attachment":openStyle;
        //1、获取文件信息
        Files files = this.iFilesService.getById(id);
        //2、更新下载次数
        if("attachment".equals(openStyle)){
            files.setDownCounts(files.getDownCounts()+1);
            this.iFilesService.updateById(files);
        }
        //2、根据文件存储路径path和文件名获取文件输出流
        String downPath = ResourceUtils.getURL("classpath:").getPath() + "/static" + files.getPath();
        //3、获取文件输入流
        FileInputStream fileInputStream = new FileInputStream(new File(downPath,files.getNewFileName()));
        //4、附件格式下载设置头部( URLEncoder.encode(files.getOldFileName(),"utf-8") 设置文件名编码风格,避免乱码)
        response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(files.getOldFileName(),"utf-8"));
        //4、获取响应输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //5、文件拷贝
        IOUtils.copy(fileInputStream,outputStream);
        //6、关闭输入输出流
        IOUtils.closeQuietly(fileInputStream);
        IOUtils.closeQuietly(outputStream);
    }

3、删除文件

    @GetMapping("/delFile")
    public String del(int id) throws FileNotFoundException {
        //1、删除本地文件数据
            //获取删除路径
        Files files = this.iFilesService.getById(id);
        String delPath = ResourceUtils.getURL("classpath:").getPath() + "static/" + files.getPath();
        File file = new File(delPath,files.getNewFileName());
        if(file.exists()){
            file.delete();
        }
        //2、删除数据库数据
        this.iFilesService.delFile(id);
        return "redirect:/file/showAll";
    }

十、定时更新下载次数

前端定时调度接口刷新下载次数

<script type="application/javascript" th:src="@{/static/js/jquery-3.5.1.min.js}"></script>
<script>
    $(()=>{
        var time ;
        $('#start').click(()=>{
            time = setInterval(()=>{
            $.get("[[@{/file/showAllJson}]]",(res)=>{
                $.each(res,(index,file)=>{
                    $("#"+file.id).text(file.downCounts)
                })
            })
        },3000);
        })
        $("#stop").click(()=>{
            clearInterval(time)
        })
    })
</script>
<body>
    <button id="start">开启定时更新</button>
    <button id="stop">关闭定时更新</button>
</body>

十一、对上面功能添加

作者一:愿有清风不解语i

我将老师的项目添加了一些小功能:

1、使用Shiro安全框架来做登录认证和拦截;

2、使用SemanticUi来稍微美化了一下界面;

3、在登录界面添加了JS代码,对表单预验证;

4、修复了在没有选择上传文件的情况下,能够上传文件的一个小bug;

5、对密码使用了MD5加密

https://github.com/HaiTang-8/File-Upload/tree/master

作者二:灵器冰

在老师的基础上,

1.增加了多用户登录注册,

2.整合layui框架美化界面和响应事件刷新表格,

3.使用shiro安全框架对页面访问进行控制。

4.为数据表格增加了分页功能。

https://github.com/sdifv/fileStorage

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1284149.html

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

相关文章

【五分钟】熟练使用numpy.cumsum()函数(干货!!!)

引言 numpy.cumsum()函数用于计算输入数组的累积和。当输入是多维数组时&#xff0c;numpy.cumsum()函数可以沿着指定轴计算累积和。 计算一维数组的累计和 代码如下&#xff1a; # 计算一维数组的累计和 tmp_array np.ones((4,), dtypenp.uint8) # [1, 1, 1, 1] print(&…

java--接口概述

1.认识接口 ①java提供了一个关键字interface&#xff0c;用这个关键字我们可以定义出一个特殊的结构&#xff1a;接口。 ②注意&#xff1a;接口不能创建对象&#xff1b;接口是用来被类实现(implements)的&#xff0c;实现接口的类称为实现类。 ③一个类可以实现多个接口(接…

1、Spring基础概念总结

Spring概述&#xff1a; Spring体系结构 IOC的概念和作用 耦合指的是对象之间的依赖关系&#xff0c;耦合越小越好 以jdbc为例 通过反射来注册驱动&#xff0c;那么会造成驱动名称写死在程序当中&#xff0c;这种结果显然是不太合理的通过配置文件的形式可以解决这种耦合问…

微服务--一篇入门kubernets

Kubernetes 1. Kubernetes介绍1.1 应用部署方式演变1.2 kubernetes简介1.3 kubernetes组件1.4 kubernetes概念 2. kubernetes集群环境搭建2.1 前置知识点2.2 kubeadm 部署方式介绍2.3 安装要求2.4 最终目标2.5 准备环境2.6 系统初始化2.6.1 设置系统主机名以及 Host 文件的相互…

成为AI产品经理——模型稳定性评估(PSI)

一、PSI作用 稳定性是指模型性能的稳定程度。 上线前需要进行模型的稳定性评估&#xff0c;是否达到上线标准。 上线后需要进行模型的稳定性的观测&#xff0c;判断模型是否需要迭代。 稳定度指标(population stability index ,PSI)。通过PSI指标&#xff0c;我们可以获得不…

Python类型注解必备利器:typing模块解读指南

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python 3.5版本后引入的typing模块为Python的静态类型注解提供了支持。这个模块在增强代码可读性和维护性方面提供了帮助。本文将深入探讨typing模块&#xff0c;介绍其基本概念、常用类型注解以及使用示例&am…

ssm农业信息管理系统源码和论文

摘 要 网络的广泛应用给生活带来了十分的便利。所以把农业信息管理与现在网络相结合&#xff0c;利用java技术建设农业信息管理系统&#xff0c;实现农业信息管理的信息化。则对于进一步提高农业信息管理发展&#xff0c;丰富农业信息管理经验能起到不少的促进作用。 农业信息…

JVM 运行时内存(三)

Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 1. 新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象&#xff0c;所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、…

分享全球顶尖的AIGC文生图资源

1 引言 人工智能正在改变许多行业的格局&#xff0c;而其中改变最直观和影响最大的就是AIGC领域的图像创作。文生图技术作为AIGC的一个重要分支&#xff0c;展现了人工智能在视觉创作领域的巨大潜力。发展至今已经有很多AI文生图平台&#xff0c;这是一次革命性的突破&#xf…

详解Hotspot的经典7种垃圾收集器原理特点与组合搭配

# 详解Hotspot的经典7种垃圾收集器原理特点与组合搭配 HotSpot共有7种垃圾收集器&#xff0c;3个新生代垃圾收集器&#xff0c;3个老年代垃圾收集器&#xff0c;以及G1&#xff0c;一共构成7种可供选择的垃圾收集器组合。 新生代与老年代垃圾收集器之间形成6种组合&#xff0c…

代码写完直接调试!IDEA插件还能这么用

IDEA是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具。 今天给大家介绍一款IDEA插件&#xff1a;Api…

Apache Sqoop使用

1. Sqoop介绍 Apache Sqoop 是在 Hadoop 生态体系和 RDBMS 体系之间传送数据的一种工具。 Sqoop 工作机制是将导入或导出命令翻译成 mapreduce 程序来实现。在翻译出的 mapreduce 中主要是对 inputformat 和 outputformat 进行定制。 Hadoop 生态系统包括&#xff1a;HDFS、Hi…

单片机系统

我们来看单片机 的例子&#xff0c;读者可能会担心单片机&#xff08;又称MCU&#xff0c;或微控制器&#xff09; 过于专业而无法理解。完全没必要&#xff01;在这里我们仅借它谈论一下有关时间的话题&#xff0c;顺带提一下单片机系统的概念。 单片机顾名思义是集成到一个芯…

【五分钟】熟练使用numpy的histogram函数(干货!!!)

histogram函数重要参数详解 def histogram(a, bins10, rangeNone, normedNone, weightsNone, densityNone):...位置参数a&#xff1a; The histogram is computed over the flattened array.&#xff08;源码对参数a的解释&#xff09; 从源码对参数a的解释来看&#xff0c;参…

[树莓派3B+][内核版本6.1]的linux内核编译+替换 (超详细)

学习Linux的内核编译&#xff0c;我使用的是x86 64位的18.04的ubuntu-linux虚拟机&#xff1a; 目录 树莓派的Linux内核源码安装 操作系统的启动过程 & Bootloader 单片机裸机&#xff1a;C51,STM32 X86&#xff0c;Intel&#xff1a;windows 嵌入式产品&#xff1a;…

深圳市左下右上百度坐标

爬取百度POI的时候&#xff0c;别人的代码中有提到左下&#xff0c;右上坐标&#xff0c;但是没有说从哪里来&#xff0c;而且还是百度的坐标。 经纬度:左下角,右上角&#xff1a;113.529103,37.444122;115.486183,38.768031 墨卡托坐标:左下角,右上角&#xff1a;12638139.45,…

由11月27日滴滴崩溃到近两个月国内互联网产品接二连三崩溃引发的感想

文章目录 知乎文分析微信聊天截图微信公众号 滴滴技术 发文k8s 官方文档滴滴官方微博账号 近两个月国内互联网产品“崩溃”事件2023-10-23 语雀崩溃2023-11-12 阿里云崩溃2023-11-27 滴滴崩溃2023-12-03 腾讯视频崩溃总结 我的感想 知乎文分析 最近连续加班&#xff0c;打车较…

d3dx9_43.dll丢失原因以及5个解决方法详解

在电脑使用过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“d3dx9_43.dll缺失”。这个错误提示通常表示我们的电脑上缺少了DirectX的一个组件&#xff0c;而DirectX是游戏和多媒体应用所必需的软件。本文将介绍d3dx9_43.dll缺失对电脑的影响以及其原因…

第0篇红队笔记-APT-HTB

nmap 80 port-web尝试 searchploit-无结果 资源隐写查看-无结果 135 port rpcclient rpcinfo.py rpcdump.py rpcmap.py rpcmap.py爆破UUID 查看该UUID的表代表的服务能搜到UUID的漏洞 IOXIDResolver提取IPv6地址 IPV6-nmap smb smb探测目录 文件下载 测试其他目录 zip文件…

不再只是android,华为自爆Harmony将对标iOS

今年10月&#xff0c;华为官方宣布&#xff0c;鸿蒙OS 4升级设备数量已突破1亿&#xff0c;成为史上升级最快的鸿蒙OS版本。 日前&#xff0c;据数码博主“定焦数码”消息&#xff0c;大厂技术员工做适配&#xff0c;通过线下沟通时&#xff0c;华为反复提到一个问题&#xff…