当前位置: 首页 > news >正文

从头开始搭建一个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测试下载示例前言 文件的上传和下载是很多系统必备的功能&#xf…...

It做形式主语和宾语

主谓宾&#xff0c;主宾能被名词性的sth&#xff0c;替换&#xff0c;如动名词&#xff0c;不定式&#xff0c;从句等等 而且&#xff0c;不能出现前面或者中间&#xff0c;很长&#xff0c;一大推的在开头或者中间&#xff0c;就产生了it做形式主宾。 一、It用作形式主语当不…...

做测试一定要知道的——软件测试流程和测试规范标准文档

目录 1、目的 2、工作范围 3、工作职责 4、测试的流程 5、测试准备阶段 6、测试方法制定阶段 7、测试执行阶段 8、bug管理 9、标准文档 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 1、目的 通…...

Linux下将一个文件压缩分包成多个小文件

压缩分包 将文件test分包压缩成1G 的文件&#xff1a; tar czf - 文件名字 | split -b 10 - 文件名.tar.gz解压 将第一步分拆的多个包解压&#xff1a; cat 文件名.tar.gz* | tar -xzv...

分享5款用了一段时间,个人觉得非常nice的软件

大家在使用Windows办公、学习的时候&#xff0c;有没有觉得自己的电脑差了点意思&#xff1f;比如&#xff1a;电脑桌面上太杂乱、装满了各类五花八门的软件、桌面壁纸不美观等。今天&#xff0c;给大家分享五款个人用了段时间后&#xff0c;觉得非常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&#xff01;&#xff01;&#xff01; Introduction Apache Spark是一个快速且通用的分布式计算引擎&#xff0c;可以在大规模数据集上进行高效的数据处理&#xff0c;包括数据转换、数据清洗、机器学习等。在本文中&#xff0c;我们将…...

趣味答题竞赛小程序开发功能的详细介绍

随着人们对知识学习的要求越来越高&#xff0c;答题已经成为了一项重要的学习和考核方式。而为了让答题变得更加有趣和富有挑战性&#xff0c;我们推出了趣味答题竞赛小程序。下面&#xff0c;我们将详细介绍这个小程序的开发功能。 1.个人淘汰赛 在个人淘汰赛中&#xff0c;…...

【独家】华为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语言杂记(指针篇)

指针篇 指针就是地址&#xff0c;地址就是指针 指针变量就是存放地址的变量 *号只有定义的时候表示定义指针变量&#xff0c;其他表示从地址里面取内容 通过指针的方法使main函数中的data1和data2发生数据交换。 #include <stdio.h> void chang_data(int *data1,int *da…...

ES window 系统环境下连接问题

环境问题&#xff1a;&#xff08;我采用的版本是 elasticsearch-7.9.3&#xff09;注意 开始修正之前的配置&#xff1a;前提&#xff1a;elasticsearch.yml增加或者修正一下配置&#xff1a;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 基本概念 我们都使用过连接池&#xff0c;比如C3P0、DBCP、hikari、Druid&#xff0c;虽然 HikariCP 的速度稍快&#xff0c;但 Druid 能够提供强大的监控和扩展功能。Druid DataSource 是阿里巴巴开发的号称为监控而生的数据库连接池&#xff0c;它不仅可以…...

maven镜像源及代理配置

在公司使用网络一般需要设置代理&#xff0c; 我在idea中创建springboot工程时&#xff0c;发现依赖下载不了&#xff0c;原以为只要浏览器设置代理&#xff0c;其他的网络访问都会走代理&#xff0c;经过查资料设置了以下几个地方后工程创建正常&#xff0c;在此记录给大家参考…...

【Java面试篇】Spring中@Transactional注解事务失效的常见场景

文章目录Transactional注解的失效场景☁️前言&#x1f340;前置知识&#x1f341;场景一&#xff1a;Transactional应用在非 public 修饰的方法上&#x1f341;场景二&#xff1a; propagation 属性设置错误&#x1f341;场景三&#xff1a;rollbackFor属性设置错误&#x1f3…...

【C】分配内存的函数

#include <stdlib.h>//分配所需的内存空间&#xff0c;并返回一个指向它的指针。 void *malloc(size_t size);//分配所需的内存空间&#xff0c;并返回一个指向它的指针。并且calloc负责把这块内存空间用字节0填//充&#xff0c;而malloc并不负责把分配的内存空间清零 vo…...

IDEA 断点总是进入class文件没有进入源文件解决

前言 idea 断点总是进入class文件没有进入源文件解决 问题 在源文件里打了断点&#xff0c;断点模式启动时却进入了class文件里的断点&#xff0c;而没有进入到java源文件里的断点。 比如&#xff1a;我在 A.java 里打了断点&#xff0c;调试时却进入到了 jar 包里的 A.clas…...

【flink】 flink入门教程demo 初识flink

文章目录通俗解释什么是flink及其应用场景flink处理流程及核心APIflink代码快速入门flink重要概念什么是flink&#xff1f; 刚接触这个词的同学 可能会觉得比较难懂&#xff0c;网上搜教程 也是一套一套的官话&#xff0c; 如果大家熟悉stream流&#xff0c;那或许会比较好理解…...

LeetCode 1487. 保证文件名唯一

【LetMeFly】1487.保证文件名唯一 力扣题目链接&#xff1a;https://leetcode.cn/problems/making-file-names-unique/ 给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹&#xff1a;在第 i 分钟&#xff0c;新建名为 names[i] 的文件夹。 由于两个…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用

阻止除自定义标签之外的所有标签 先输入一些标签测试&#xff0c;说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时&#xff08;如通过点击或键盘导航&…...

41道Django高频题整理(附答案背诵版)

解释一下 Django 和 Tornado 的关系&#xff1f; Django和Tornado都是Python的web框架&#xff0c;但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架&#xff0c;鼓励快速开发和干净、实用的设计。它遵循MVC设计&#xff0c;并强调代码复用。Django有…...

Vue 实例的数据对象详解

Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...