从头开始搭建一个SpringBoot项目--SpringBoot文件的上传与下载
从头开始搭建一个SpringBoot项目--SpringBoot文件的上传
- 前言
- 流程分析
- 代码
- 结构
- 代码详情
- UploadFileInfo.class
- UploadController.class
- UploadDao.class
- UploadDao.xml
- UploadServices.class
- UploadServicesImpl.class
- 测试
- 下载
- 示例
前言
文件的上传和下载是很多系统必备的功能,之前的一篇文章简单描述了下载,那么现在我们来实现上传文件并且存储到服务器。
值得注意的是,在以下的示例系统中,我已经引入了SpringSecurity、Swagger、Mybatis等框架了。
详情参考: 从头开始搭建一个SpringBoot项目–SpringSecurity的配置
流程分析
用户上传文件,第一步肯定是选择文件,然后系统接收文件并保存到服务器,这一步里面我们首先要做的应该是获取此次上传信息,比如上传人、上传时间、上传文件类型等等。剩下的就是需要考虑的问题是,如何保存?
我的意思是如何保存这个文件?比如文件名称,如果有两个用户上传了一个同样名字的文件,那我们就让用户保存吗?那肯定是不可以的。所以保存时候很重要的一点就是,文件不能同名。所以这里我们保存在服务器上的文件名称最好做一个映射:用户定义文件名 -- 服务器保存文件名称。这种映射关系可以保存在数据库中,这样就保证了文件名的唯一性。
比如用户上传文件名称为你遭老罪了.png,保存的时候用一个时间戳或者uuid + 文件后缀作为该文件在服务器上的名称,假设为:123456789.png,然后把你遭老罪了--123456789,这样的一个映射关系保存到数据库里面,这样用户要按照文件名从服务器上获取该文件的时候我们也能的找到,保存的时候也不会有同名的风险。
PS: 同名风险还是有的,虽然很小,但确实存在:UUID可能生成相同,时间戳可能多用户上传时一样,如果需要的话保存前可以做一个文件名同名检查。如果文件名已存在,则再生成一个。
上传文件的流程图的话大致是以下这样:

代码
结构

代码详情
UploadFileInfo.class
@Setter
@Getter
@ToString
@NoArgsConstructor
public class UploadFileInfo {@ApiModelProperty(value = "上传人id")int uploaderId;@ApiModelProperty(value = "上传人名称")String uploaderName;@ApiModelProperty(value = "上传人时间")String uploadTime;@ApiModelProperty(value = "上传文件大小")int size;@ApiModelProperty(value = "上传文件名称")String fileName;@ApiModelProperty(value = "上传文件唯一名称")String uName;@ApiModelProperty(value = "存储路径")String storePath;@ApiModelProperty(value = "文件后缀")String extension;public UploadFileInfo(UserBean userBean) {if (userBean == null)throw new RuntimeException("用户为空");this.uploaderId = userBean.getId();this.uploaderName = userBean.getUsername();}
}
UploadController.class
这里面的日期工具类在我的其他文章里 主页搜索日期就可找到。
@RestController
@Controller
@RequestMapping(value = "/upload/")
@Api(tags = "03 上传文件" , position = 3)
public class UploadController {//配置文件中保存的位置@Value("${root.upload.path}")private String uploadPath;@AutowiredUploadServices uploadServices;@ApiOperation(value = "上传文件测试" , notes = "支持所有文件")@PostMapping(value = "/uploadTest")public Result uploadFile(@RequestParam(required = true) MultipartFile file) {UploadFileInfo up = getUploadInfo(file);System.out.println(up.toString());if(uploadServices.addUploadInfo(up) <= 0) {return ResultUtil.success(ResultCode.ERROR);}try {//将当前文件保存到服务器指定目录下的文件file.transferTo(new File(up.getStorePath()));}catch (Exception e) {e.printStackTrace();}return ResultUtil.success(ResultCode.SUCCESS);}/*** @Description* @Param file* @Return {@link UploadFileInfo}* @Author 三文鱼先生* @Date 2023/3/2 10:45**/public UploadFileInfo getUploadInfo(MultipartFile file) {UserBean user = (UserBean) SecurityContextHolder.getContext().getAuthentication().getPrincipal();//设置上上传人基本信息UploadFileInfo uploadFileInfo = new UploadFileInfo(user);//文件存储时的唯一idString uName = UUID.randomUUID().toString().replaceAll("-" , "");//当前时间uploadFileInfo.setUploadTime(DateUtil.formatStr(new Date() , DateUtil.SecondPattern));//文件大小uploadFileInfo.setSize((int) file.getSize());String[] fileName = file.getOriginalFilename().split("\\.");String extension = fileName[1];//存储路径String storePath = uploadPath + uName + "." + extension;//上传文件后缀uploadFileInfo.setExtension(extension);//服务器存储地址uploadFileInfo.setStorePath(storePath);//使用uuid作为文件在服务器上的名称uploadFileInfo.setUName(uName);//文件的真实名称uploadFileInfo.setFileName(fileName[0]);return uploadFileInfo;}}
UploadDao.class
public interface UploadDao {//添加上传文件记录信息int addUploadInfo(UploadFileInfo uploadFileInfo);
}
UploadDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.demo.uploadfile.dao.UploadDao"><insert id="addUploadInfo" parameterType="com.demo.uploadfile.bean.UploadFileInfo">insert into my_file(uploaderId,uploaderName,uploadTime,size,fileName,uName,storePath,extension) values(#{uploaderId},#{uploaderName},#{uploadTime},#{size},#{fileName},#{uName},#{storePath},#{extension});</insert>
</mapper>
UploadServices.class
public interface UploadServices {int addUploadInfo(UploadFileInfo uploadFileInfo);
}
UploadServicesImpl.class
@Service
public class UploadServicesImpl implements UploadServices {@AutowiredUploadDao uploadDao;@Overridepublic int addUploadInfo(UploadFileInfo uploadFileInfo) {return uploadDao.addUploadInfo(uploadFileInfo);}
}
测试


下载
下载的话就比较简单了,这里在之前的文章: 记SpringBoot下载的两种方式,在这里需要注意的应该是,配置SpringSecurity配置下不拦截/file/**。

示例
图片文件可以查看后 右键自定义保存

其他文件诸如:doc、excel、rar等都会直接下载。

相关文章:
从头开始搭建一个SpringBoot项目--SpringBoot文件的上传与下载
从头开始搭建一个SpringBoot项目--SpringBoot文件的上传前言流程分析代码结构代码详情UploadFileInfo.classUploadController.classUploadDao.classUploadDao.xmlUploadServices.classUploadServicesImpl.class测试下载示例前言 文件的上传和下载是很多系统必备的功能…...
It做形式主语和宾语
主谓宾,主宾能被名词性的sth,替换,如动名词,不定式,从句等等 而且,不能出现前面或者中间,很长,一大推的在开头或者中间,就产生了it做形式主宾。 一、It用作形式主语当不…...
做测试一定要知道的——软件测试流程和测试规范标准文档
目录 1、目的 2、工作范围 3、工作职责 4、测试的流程 5、测试准备阶段 6、测试方法制定阶段 7、测试执行阶段 8、bug管理 9、标准文档 总结感谢每一个认真阅读我文章的人!!! 重点:配套学习资料和视频教学 1、目的 通…...
Linux下将一个文件压缩分包成多个小文件
压缩分包 将文件test分包压缩成1G 的文件: tar czf - 文件名字 | split -b 10 - 文件名.tar.gz解压 将第一步分拆的多个包解压: cat 文件名.tar.gz* | tar -xzv...
分享5款用了一段时间,个人觉得非常nice的软件
大家在使用Windows办公、学习的时候,有没有觉得自己的电脑差了点意思?比如:电脑桌面上太杂乱、装满了各类五花八门的软件、桌面壁纸不美观等。今天,给大家分享五款个人用了段时间后,觉得非常nice的软件。 1.鼠标可视化…...
搜广推 Product-based Neural Networks (PNN) - 改进特征交叉的方式
😄 PNN:2016年上海交通大学提出。 文章目录 1、PNN1.1、原理1.2、创新点:product层1.3、product层z部分的输出:l~z~ 的计算方式:1.4、product层z部分的输出:l~p~ 的计算方式:1.4.1、IPNN1.4.2、OPNN1.5、优点1.6、缺点Reference1、PNN PNN:Product-based Neural Netwo…...
IDEA2022 配置spark开发环境
本人强烈建议在 linux环境下 学习 spark!!! Introduction Apache Spark是一个快速且通用的分布式计算引擎,可以在大规模数据集上进行高效的数据处理,包括数据转换、数据清洗、机器学习等。在本文中,我们将…...
趣味答题竞赛小程序开发功能的详细介绍
随着人们对知识学习的要求越来越高,答题已经成为了一项重要的学习和考核方式。而为了让答题变得更加有趣和富有挑战性,我们推出了趣味答题竞赛小程序。下面,我们将详细介绍这个小程序的开发功能。 1.个人淘汰赛 在个人淘汰赛中,…...
【独家】华为OD机试提供C语言题解 - 获取最大软件版本号
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明获取…...
k8s编程operator实战之云编码平台——⑤项目完成、部署
文章目录1、效果展示2、保存用户状态和访问用户服务实现方案2.1 如何保存用户的状态2.1.1 解决保留安装的插件问题2.2 如何访问到用户在工作空间中启动的http服务2.2.1 code-server如何帮我们实现了用户程序的代理3、Operator功能实现3.1 使用KubeBuilder创建项目3.1.1 完善kin…...
C语言杂记(指针篇)
指针篇 指针就是地址,地址就是指针 指针变量就是存放地址的变量 *号只有定义的时候表示定义指针变量,其他表示从地址里面取内容 通过指针的方法使main函数中的data1和data2发生数据交换。 #include <stdio.h> void chang_data(int *data1,int *da…...
ES window 系统环境下连接问题
环境问题:(我采用的版本是 elasticsearch-7.9.3)注意 开始修正之前的配置:前提:elasticsearch.yml增加或者修正一下配置:xpack.security.enabled: truexpack.license.self_generated.type: basicxpack.secu…...
hexo部署github搭建个人博客 完整详细带图版(更新中)
文章目录0. 前置内容1. hexo创建个人博客2. GitHub创建仓库3. hexo部署到GitHub4. 常用命令newcleangenerateserverdeploy5. 添加插件5.1 主题5.2 博客基本信息5.3 创建新的菜单5.4 添加搜索功能5.5 添加阅读时间字数提示5.6 打赏功能5.7 切换主题5.8 添加不蒜子统计5.9 添加百…...
SpringBoot集成DruidDataSource实现监控 SQL 性能
一、快速入门 1.1 基本概念 我们都使用过连接池,比如C3P0、DBCP、hikari、Druid,虽然 HikariCP 的速度稍快,但 Druid 能够提供强大的监控和扩展功能。Druid DataSource 是阿里巴巴开发的号称为监控而生的数据库连接池,它不仅可以…...
maven镜像源及代理配置
在公司使用网络一般需要设置代理, 我在idea中创建springboot工程时,发现依赖下载不了,原以为只要浏览器设置代理,其他的网络访问都会走代理,经过查资料设置了以下几个地方后工程创建正常,在此记录给大家参考…...
【Java面试篇】Spring中@Transactional注解事务失效的常见场景
文章目录Transactional注解的失效场景☁️前言🍀前置知识🍁场景一:Transactional应用在非 public 修饰的方法上🍁场景二: propagation 属性设置错误🍁场景三:rollbackFor属性设置错误dz…...
【C】分配内存的函数
#include <stdlib.h>//分配所需的内存空间,并返回一个指向它的指针。 void *malloc(size_t size);//分配所需的内存空间,并返回一个指向它的指针。并且calloc负责把这块内存空间用字节0填//充,而malloc并不负责把分配的内存空间清零 vo…...
IDEA 断点总是进入class文件没有进入源文件解决
前言 idea 断点总是进入class文件没有进入源文件解决 问题 在源文件里打了断点,断点模式启动时却进入了class文件里的断点,而没有进入到java源文件里的断点。 比如:我在 A.java 里打了断点,调试时却进入到了 jar 包里的 A.clas…...
【flink】 flink入门教程demo 初识flink
文章目录通俗解释什么是flink及其应用场景flink处理流程及核心APIflink代码快速入门flink重要概念什么是flink? 刚接触这个词的同学 可能会觉得比较难懂,网上搜教程 也是一套一套的官话, 如果大家熟悉stream流,那或许会比较好理解…...
LeetCode 1487. 保证文件名唯一
【LetMeFly】1487.保证文件名唯一 力扣题目链接:https://leetcode.cn/problems/making-file-names-unique/ 给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹:在第 i 分钟,新建名为 names[i] 的文件夹。 由于两个…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
