【RuoYi】实现文件的上传与下载

一、前言

   首先,最近在做一个管理系统,里面刚好需要用到echarts图和富文本编辑器,然后我自己去看了官网觉得有点不好懂,于是去B站看来很多视频,然后看到了up主【程序员青戈】的视频,看了他讲的echarts图和富文本编辑器部分的内容,觉得讲的很好,很推荐大家去观看他的视频。然后在富文本编辑器这部分内容中,需要用到,文件上传与下载的部分知识,所以这里做一个笔记,来记录关于这部得分的内容,echarts图和富文本编辑器部分的内容也会在后面的博客中介绍。希望对大家有所帮助啦~

二、准备工作

   导入hutool的依赖

        <!--hutool工具类-->
        <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.25</version>
        </dependency>

三、文件上传与下载代码

   如下所示,是跟着青戈学的已经封装好的代码,大家可以直接拿来用。但是需要注意的是,我用的是RuoYi的框架,所以最后返回的是RuoYi封装好的AjaxResult结果集,而不是青戈自己写的Result结果集,就这里需要注意以下。

@RestController
@Api(tags = "文件上传与下载模块")
@RequestMapping("/file")
public class FileController extends BaseController {
    @Value("${ip:localhost}")
    String ip;//通过配置文件拿到ip

    @Value("${server.port}")
    String port;

    private static final String ROOT_PATH = System.getProperty("user.dir")+ File.separator+"files";//文件根目录
    @ApiOperation(value = "文件上传")
    @PostMapping("/upload")
    public AjaxResult Upload(@RequestPart("file") MultipartFile file) throws IOException {//MultipartFile file 输入的文件
        String originalFilename = file.getOriginalFilename();//originalFilename是获取源文件名
        String mainName = FileUtil.mainName(originalFilename);// mainName 是主文件名
        String extName = FileUtil.extName(originalFilename);//extName 是文件的标识 png、pdf等
        if(!FileUtil.exist(ROOT_PATH)){//通过hutool工具类中的FileUtil来判断我们的根目录是否存在,若不存在则在根目录下创建file文件夹
            FileUtil.mkdir(ROOT_PATH);
        }
        //判断file文件夹中传入的文件是否存在,若存在为了防止重名不被替换,则需要对文件重新命名
        if(FileUtil.exist(ROOT_PATH+File.separator+originalFilename)){
            originalFilename=System.currentTimeMillis()+"_"+mainName+"."+extName;
        }
        File saveFile = new File(ROOT_PATH + File.separator + originalFilename);//创建一个file文件对象,方便写入磁盘
        file.transferTo(saveFile);//存储文件到本地磁盘里面去
        String url ="http://"+ip+":"+port+"/file/download/"+originalFilename;//问价下载的路径
        return AjaxResult.success(url);//RuoYi自带的结果集
    }


    @ApiOperation(value = "文件下载")
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName, HttpServletResponse response) throws IOException {
//        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));//文件下载
        response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(fileName,"UTF-8"));//文件预览
        String filePath = ROOT_PATH+File.separator+fileName;//拿到文件的路径
        if(!FileUtil.exist(filePath)){//文件不存在,就不用管,因为没有东西可写
            return;
        }
        byte[] bytes = FileUtil.readBytes(filePath);//使用FileUtil从filePath中去读取文件
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(bytes);//把文件的字节数写出去
        outputStream.flush();//刷新一下
        outputStream.close();//一定要关闭文件流
    }
}

接口测试

我们在测试接口时,可以直接使用RuoYi框架为我们提供的Swagger来测试接口,当然也可以用PostMan,看个人的习惯来定了。

bbe54ea0ff974437a3f132f5fe6e4682.png

a6711e0d31e147cba7d4d9d88e5f4805.png

8a7c4224decc43f6beff175d7cbf0dc1.png

文件上传成功返回码为200,而且在Idea中生成file文件夹

1242212e892b4a4c9a311d464e4791e0.png

57a9f1faf2304ae78ca45bd3552d37e3.png

到此我们的文件上传与下载的接口就完成了,接下来我们来看看如何在前端使用我们的该功能。

四、实践

①单文件上传

da561baecfeb49de9762768906024a99.png

如上图所示,我们现在要完成一个点击功能,从而实现用户头像的上传与显示,这个功能也是我们在做项目中很常见的功能。

思路:上传图片->保存数据库->再从数据库拿到图片路径

先完成文件的上传:

05f047e215dc457885107c79fd926ed3.png

注意:我们使用的是RuoYi框架中的AjaxResult结果集,返回的数据是在response下的msg中

bf68590f7fa04edfa67326fb10bbb101.png

JS中代码

    handleTableFileUpload(row,file,fileList){
      console.log(row,file)
      row.stuAvatar=file.response.msg//注意我们使用的是RuoYi框架中的AjaxResult结果集,返回的数据是在response下的msg中
      //触发更新
      //使用RuoYi中封装好的updateStudent()函数,将当前对象更新
      updateStudent(row).then(response => {
        if(response.code=='200'){
          this.$message.success("上传成功")
        }else{
          this.$message.success("上传失败")
        }
        this.form = response.data;
      });
    }

头像显示代码:

7cd6da79d60a4fc694edec61a9fa41d0.png

效果如下:

8fa802193bf14a8e9bcc4058517616ad.png

②多文件上传

多文件其实是基于单文件的,就是在单文件的基础上,多次请求即可。我们也可以做个简单的案例测试。先在element-ui随便找一个文件上传的前端页面,如下图所示:

b15d1a2133634dcc904d108af8057a05.png

放在我们的RuoYi的项目中:

2a01bafe498047b691df4e098c9116ee.png

400e8f62200e4730ad4d25a0ffc7bcc0.png

12b6eeabdec94234bd1b3455f7c98009.png

测试:

74b57ed4df6f43ed9b7d584848596aff.png

a4c3d68d69704cc4aed5f279629a5995.png

如上图所示,我们可以成功的拿到三张图片的地址,此时我们只需要,将其存入数据库,再从数据库中拿出来显示即可,大家下来试一试即可,我这里就不做测试了。

五、总结

   跟着青戈学习了这个文件上传与下载的的视频,自己真的学到了很多,这个文件上传下载的功能不仅适用于图片,也可以用在pdf、word等文件中,也希望这些内可以帮助屏幕前的小伙伴们,如果有所帮助,别忘了点赞、关注一波哦~

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

社交媒体数据恢复:飞信

请注意&#xff0c;本教程只适用于飞信&#xff0c;并且不涉及推荐任何数据恢复软件。 一、备份飞信聊天记录 在开始恢复飞信聊天记录之前&#xff0c;我们建议您先备份现有的聊天记录。这样&#xff0c;即使恢复过程中出现问题&#xff0c;您也可以通过备份文件找回重要的聊…

搭建基于Django的博客系统增加广告轮播图(三)

上一篇&#xff1a;ChatGPT搭建博客Django的web网页添加用户系统&#xff08;二&#xff09; 下一篇&#xff1a;搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL&#xff08;四&#xff09; 功能概述 增加轮播图显示广告信息。 需求详细描述 1. 增加轮播图显示广告信…

python解决flask启动的同时启动定时任务

业务场景描述&#xff1a;在常规的开发中&#xff0c;我们开发接口服务&#xff0c;一般会将数据放在数据库、文件等第三方文件&#xff0c;启动服务后&#xff0c;服务到后台数据库中加载数据&#xff0c;这样做的好处当然是开发会更加便利以及数据的可复用性较高&#xff0c;…

一键实现文件夹批量高效重命名:轻松运用随机一个字母命名,让文件管理焕然一新!

在数字化时代&#xff0c;文件夹管理是我们日常生活和工作中不可或缺的一部分。然而&#xff0c;随着文件数量的不断增加&#xff0c;文件夹命名的繁琐和重复成为了一个让人头疼的问题。你是否曾因为手动一个个重命名文件夹而感到枯燥乏味&#xff1f;你是否曾渴望有一种方法能…

arm cortex-m架构 SVC指令详解以及其在freertos的应用

1. 前置知识 本文基于arm cortex-m架构描述&#xff0c; 关于arm cortex-m的一些基础知识可以参考我另外几篇文章&#xff1a; arm cortex-m 架构简述arm异常处理分析c语言函数调用规范-基于arm 分析 2 SVC指令 2.1 SVC指令位域表示 bit15 - bit12&#xff1a;条件码&#…

深入分析 Android BroadcastReceiver (一)

文章目录 深入分析 Android BroadcastReceiver (一)1. Android BroadcastReceiver 设计说明1.1 BroadcastReceiver 的主要用途 2. BroadcastReceiver 的工作机制2.1 注册 BroadcastReceiver2.1.1 静态注册2.1.2 动态注册 3. BroadcastReceiver 的生命周期4. 实现和使用 Broadca…

Android下HWC以及drm_hwcomposer普法(上)

Android下HWC以及drm_hwcomposer普法(上) 引言 按摩得全套&#xff0c;错了&#xff0c;做事情得全套&#xff0c;普法分析也是如此。drm_hwcomposer如果对Android图形栈有一定研究的童鞋们应该知道它是Android提供的一个的图形后端合成处理HAL模块的实现。但是在分析这个之前…

yolov8使用:数据格式转换(目标检测、图像分类)多目标跟踪

安装 yolov8地址&#xff1a;https://github.com/ultralytics/ultralytics git clone https://github.com/ultralytics/ultralytics.git安装环境&#xff1a; pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple目标检测 标注格式转换 若使用 labelimg…

sql注入-布尔盲注

布尔盲注&#xff08;Boolean Blind SQL Injection&#xff09;是一种SQL注入攻击技术&#xff0c;用于在无法直接获得查询结果的情况下推断数据库信息&#xff1b;它通过发送不同的SQL查询来观察应用程序的响应&#xff0c;进而判断查询的真假&#xff0c;并逐步推断出有用的信…

微服务学习Day9

文章目录 分布式事务seata引入理论基础CAP定理BASE理论 初识Seata动手实践XA模式AT模式TCC模式SAGA模式 高可用 分布式事务seata 引入 理论基础 CAP定理 BASE理论 初识Seata 动手实践 XA模式 AT模式 TCC模式 Service Slf4j public class AccountTCCServiceImpl implements A…

C语言 | Leetcode C语言题解之第126题单词接龙II

题目&#xff1a; 题解&#xff1a; char** list; int** back; int* backSize;// DFS uses backtrack information to construct results void dfs(char*** res, int* rSize, int** rCSizes, int* ans, int last, int retlevel) {int i ans[last];if (i 0) {res[*rSize] (c…

DALL·E 2详解:人工智能如何将您的想象力变为现实!

引言 DALLE 2是一个基于人工智能的图像生成模型&#xff0c;它通过理解自然语言描述来生成匹配这些描述的图像。这一模型的核心在于其创新的两阶段工作流程&#xff0c;首先是将文本描述转换为图像表示&#xff0c;然后是基于这个表示生成具体的图像。 下面详细介绍DALL-E2的功…

Vivado Design Suite一级物件

Vivado Design Suite一级物件 按设计过程导航内容 Xilinx文档围绕一组标准设计流程进行组织&#xff0c;以帮助您 查找当前开发任务的相关内容。本文件涵盖 以下设计过程&#xff1a; •硬件、IP和平台开发&#xff1a;为硬件创建PL IP块 平台&#xff0c;创建PL内核&#xff0…

HTML的标签(标题、段落、文本、图片、列表)

HTML的标签1 标题标签&#xff1a;段落标签&#xff1a;文本标签&#xff1a;图片标签:列表标签&#xff1a;有序列表&#xff1a;无序列表&#xff1a;定义列表&#xff1a;列表案例&#xff1a; 标题标签&#xff1a; 标签&#xff1a;h1~h6 注意&#xff1a;如果使用无效标…

C语言怎样写数据⽂件,使之可以在不同字⼤⼩、 字节顺序或浮点格式的机器上读⼊?

一、问题 怎样写数据⽂件&#xff0c;使之可以在不同字⼤⼩、字节顺序或浮点格式的机器上读⼊&#xff0c;也就是说怎样写⼀个可移植性好的数据⽂件&#xff1f; 二、解答 最好的移植⽅法是使⽤⽂本⽂件&#xff0c;它的每⼀字节放⼀个 ASCII 代码&#xff0c;代表⼀个字符。 …

从JS角度直观理解递归的本质

让我们写一个函数 pow(x, n)&#xff0c;它可以计算 x 的 n 次方。换句话说就是&#xff0c;x 乘以自身 n 次。 有两种实现方式。 迭代思路&#xff1a;使用 for 循环&#xff1a; function pow(x, n) {let result 1;// 在循环中&#xff0c;用 x 乘以 result n 次for (let i…

短时间内如何顺利通过 Java 面试?

今天我们来探讨一个重要的话题&#xff1a;短时间内如何顺利通过 Java 面试&#xff1f; 在此之前&#xff0c;我正在精心编写一套完全面向小白的 Java 自学教程&#xff0c;我相信这套教程会非常适合正在努力提升的你。教程里面涵盖了丰富全面的编程教学内容、详细生动的视频…

2.8Flowmap的实现

一、Flowmap 是什么 半条命2中水的流动 求生之路2中的水的流动 这种方式原理简单&#xff0c;容易实现&#xff0c;运算量少&#xff0c;如今也还在使用 1.flowmap的实质 Flow map(流向图) &#xff0c;一张记录了2D向量信息的纹理&#xff0c;Flow map上的颜色(通常为RG通道…

Python知识点14---被规定的资源

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 在Python中被规定的东西不止有常识中的那些关键字、构造器等编程语言…

Vue3-Ref Reactive toRef toRefs对比学习、标签ref与组件ref

响应式数据&#xff1a; Ref 作用&#xff1a;定义响应式变量。 语法&#xff1a;let xxx ref(初始值)(里面可以是任何规定内类型、数组等)。 返回值&#xff1a;一个RefImpl的实例对象&#xff0c;简称ref对象或ref&#xff0c;ref对象的value属性是响应式的。 注意点&am…