基于若依的文件上传、下载
基于若依实现文件上传、下载
文章目录
- 基于若依实现文件上传、下载
- 1、前端实现-文件上传
- 1.1 通用上传分析
- 1.2 修改实现上传接口
- 2、后端实现-文件上传
- 3、后端实现-文件下载
- 4、前端实现-文件下载
官网其实也写了,但是我是自己改造封装了一下,再次迈向全栈的一小步。下面是官网前后端分离版本文件上传的地址:
若依官方文档
1、前端实现-文件上传
1.1 通用上传分析
首先我这里有一个书籍列表的基础页面,我在它的修改这一栏加上了文件上传,这里前端其实就是用了若依封装的一个全局文件上传的组件,如果想看它的底层逻辑可以直接main.js,我这里就直接用了(但是后来发现全局组件不能行,还得自己封装elemntui的组件upload,这里只是先分析逻辑)
注意这里只是先分析,实现还在后面,因为若依自带的通用文件上传我们不能调用自己的上传接口,保存文件信息到数据库
这里就是找到对应的修改的dialog对话框中的form加上全局组件 <file-upload v-model="form.file"/>
就可以了
<!-- 添加或修改对话框 --><el-dialog :title="title" :visible.sync="open" width="500px" append-to-body><el-form ref="form" :model="form" :rules="rules" label-width="80px"><!--这里其他不重要的字段只列举了一部分--><el-form-item label="图书类型" prop="bookType"><el-select v-model="form.bookType" placeholder="请选择图书类型"><el-option label="名著" value="1"></el-option><el-option label="历史" value="2"></el-option><el-option label="社科" value="3"></el-option></el-select></el-form-item><el-form-item label="出版日期" prop="publishDate"><el-date-picker clearablev-model="form.publishDate"type="date"value-format="yyyy-MM-dd"placeholder="请选择出版日期"></el-date-picker></el-form-item><!--文件上传字段--><el-form-item label="上传文件" prop="file"><file-upload v-model="form.file"/></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">确 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog>
然后我们在修改对话框中点击上传文件,就会发现它直接调用了后端通用的上传文件的接口,已经把文件上传到了服务器,并且返回了上传后的地址
/*** 通用上传请求(单个)*/@PostMapping("/upload")public AjaxResult uploadFile(MultipartFile file) throws Exception{try{// 上传文件路径 ,已在配置文件配置D:/ruoyi/uploadPathString filePath = RuoYiConfig.getUploadPath();// 上传并返回新文件名称 这里其实就在电脑配置的地址 根据年月日可以看文件了String fileName = FileUploadUtils.upload(filePath, file);String url = serverConfig.getUrl() + fileName;AjaxResult ajax = AjaxResult.success();ajax.put("url", url);ajax.put("fileName", fileName);ajax.put("newFileName", FileUtils.getName(fileName));ajax.put("originalFilename", file.getOriginalFilename());return ajax;}catch (Exception e){return AjaxResult.error(e.getMessage());}}
上面就是FileUploadUtils.upload(filePath, file);
上传后的文件,下面是通用上传接口返回的响应,自己可以先看清楚,对于这个新的文件名称fileName 其实就是去掉了前缀的配置地址然后加上了一个profile,这个是为了隐藏我们真实的配置的文件路径,把配置的地址映射为了profile
但是这里其实可能不是我们想要的,**因为我们想调用我们自己的上传接口,这样我们后端还可以对文件进行处理,比如拿到文件后缀,把文件存入数据库对应的字段等。
1.2 修改实现上传接口
所以我们只能自己基于elemntui 去做修改,这里我想上传成功后还要返显文件名称
在列表的form加一个文件名称字段,
<el-table-column label="文件名称" align="center" prop="fileName" />
首先对新增和修改的dialog做修改
<!-- 添加或修改对话框 --><el-dialog :title="title" :visible.sync="open" width="500px" append-to-body><el-form ref="form" :model="form" :rules="rules" label-width="80px"><!--其他字段就省略了--><!--文件上传字段--><el-form-item label="上传文件" ><!--这里上传成功后会绑定文件名到form.fileName字段传给后端的新增接口,uploadBookFile定义上传请求, :before-upload是上传前的回调,用于文件格式校验 --><el-uploadclass="upload-demo"action="#":http-request="uploadBookFile":drag="true":before-upload="uploadFileFun":headers="upload.headers":file-list="form.fileList"><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><div class="el-upload__tip fontSize12 colorRed" slot="tip">上传文件格式为word或pdf或者txt,文件大小在2M以内</div></el-upload></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm">确 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog>
data 数据
upload: {// 设置上传的请求头部headers: { Authorization: "Bearer " + getToken() },},// 表单参数form: {},
javaScript方法
import { uploadBookFile} from "@/api/system/book";//下面是method写在里面的, 这里就是上传功能向后端发送上传请求,参数是一个二进制文件uploadBookFile(file){console.log(file.file,151454)// 创建formdata实例let formData = new window.FormData();// 将获取的文件通过append方法加入实例中formData.append("file", file.file);//发送axios请求uploadBookFile(formData).then(res => {console.log(res)//拿到后端响应的文件名称反显到列表的formthis.form.fileName = res.originalFilename})},//文件上传前的校验uploadFileFun(file){var test = /(doc|docx|pdf|txt)$/.test(file.name.split('.').pop().toLowerCase());if (!test) {this.$message.error("请上传正确的文档格式!");return false;}const isLt2M = file.size / 1024 / 1024 < 2;if (!isLt2M) {this.$message.error("上传文件大小不能超过 2MB!");return false;}},/** 提交按钮 */submitForm() {this.$refs["form"].validate(valid => {if (valid) {if (this.form.id != null) {updateBook(this.form).then(response => {this.$modal.msgSuccess("修改成功");this.open = false;this.getList();});} else {addBook(this.form).then(response => {this.$modal.msgSuccess("新增成功");this.open = false;this.getList();});}}});},
api/book.js
import { getToken } from "@/utils/auth";
// 上传文件
export function uploadBookFile(data) {return request({url: '/system/book/uploadFile',method: 'post',data: data,headers: {'Content-Type': 'multipart/form-data','Authorization': "Bearer " + getToken(),}})
}
2、后端实现-文件上传
后端其实就比较简单了,我也没做一个专门的文件表,只是在业务表里面加了一个file_name字段,表结构如下**(这里只是做文件上传,所以不需要文件路径字段,后续做文件下载就必须要文件路径字段,后面我会再修改)**
controller 这里是前端的upload组件传过来了一个二进制文件,然后后端把文件上传到服务器,并把文件名也返回给了前端,这样前端就可以对响应结果做解析,把文件名字段绑定到新增、修改的dialog里面,然后点击保存再把文件名称字段传回后端保存到数据库。
/*** 上传文件接口* @param file* @return* @throws Exception*/@PostMapping("/uploadFile")public AjaxResult uploadFile(MultipartFile file) throws Exception{try{// 上传文件路径 ,已在配置文件配置D:/ruoyi/uploadPathString filePath = RuoYiConfig.getUploadPath();// 上传并返回新文件名称 . "fileName": "/profile/upload/2024/07/06/紫金项目_20240706155317A001.txt",String fileName = FileUploadUtils.upload(filePath, file);String url = serverConfig.getUrl() + fileName;//这些信息返回给前端之后,AjaxResult ajax = AjaxResult.success();ajax.put("url", url);ajax.put("fileName", fileName);// "newFileName": "紫金项目_20240706155317A001.txt",ajax.put("newFileName", FileUtils.getName(fileName));// "originalFilename": "紫金项目.txt",用于给前端列表回显ajax.put("originalFilename", file.getOriginalFilename());return ajax;}catch (Exception e){return AjaxResult.error(e.getMessage());}}/*** 新增接口就是代码生成的看的,前端点击保存按钮的时候会读取Book实体类的fileName字段再保存到数据库*/@PreAuthorize("@ss.hasPermi('system:book:add')")@Log(title = "新增", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@RequestBody Book book){return toAjax(bookService.insertBook(book));}
3、后端实现-文件下载
由于实现文件下载,所以必不可少的就是文件路径
这个字段,所以我们还得加上文件路径
这个字段,所以现在表结构如下,还得给所有的增删改查字段加上文件路径这个字段
其他的直接使用通用的文件下载接口就可以了 ,前端传一个文件路径回来,后端就可以直接下载了
前端需要传的文件路径是这样的 /profile/upload/2024/07/06/紫金项目_20240706160309A002.txt
首先前端经过代理proxy之后就会拿到ip和端口,然后后端这时候有个拦截器,它会拦截/profile
,拦截之后把它再替换成配置文件中配置的绝对路径。
4、前端实现-文件下载
首先修改文件上传方法,加入一行 this.form.filePath = res.fileName
,这样上传后,把文件路径绑定到了西新增修改的dialong,在点击保存的时候,就可以把文件路径存入数据库。后续列表查询就可以读取到当前行的文件路径了。
uploadBookFile(file){console.log(file.file,151454)// 创建formdata实例let formData = new window.FormData();// 将获取的文件通过append方法加入实例中formData.append("file", file.file);uploadBookFile(formData).then(res => {console.log(res)// 保存到新增、修改的form里面再入数据库this.form.fileName = res.originalFilenamethis.form.filePath = res.fileName})},
加上下载按钮
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"><template slot-scope="scope"><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleUpdate(scope.row)"v-hasPermi="['system:book:edit']">修改</el-button><el-buttonsize="mini"type="text"icon="el-icon-delete"@click="handleDelete(scope.row)"v-hasPermi="['system:book:remove']">删除</el-button><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleDownload(scope.row)">下载</el-button></template></el-table-column>
在method里面加上如下方法,这里就是直接调用了通用的文件下载,这里的filePanth就是前面保存的/profile/upload/2024/07/06/紫金项目_20240706160309A002.txt
handleDownload(row){var name = row.fileName;var url = row.filePath;this.$download.resource(url,false)}
最后值得注意的是我目前实现的都是单文件上传和下载,多文件我后续会继续写demo
相关文章:

基于若依的文件上传、下载
基于若依实现文件上传、下载 文章目录 基于若依实现文件上传、下载1、前端实现-文件上传1.1 通用上传分析1.2 修改实现上传接口 2、后端实现-文件上传3、后端实现-文件下载4、前端实现-文件下载 官网其实也写了,但是我是自己改造封装了一下,再次迈向全栈…...

论文回顾 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法
论文速览 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法 1 引言 在计算机视觉和机器人领域,相机校准一直是一个基础而又重要的问题。传统的相机校准方法主要依赖于从已知校准图案中提取角点,然后通过优化算法求解相机的内参和外参。这…...
高级java每日一道面试题-2024年7月1日
题目:请解释 Java 中的内存泄漏,并说明如何检测和避免内存泄漏。 答案: 内存泄漏指的是程序中不再使用的对象,由于某些原因没有被垃圾回收器回收,仍然占据着内存空间,导致可用内存逐渐减少,最…...

当需要对多个表进行联合更新操作时,怎样确保数据的一致性?
文章目录 一、问题分析二、解决方案三、示例代码(以 MySQL 为例)四、加锁机制示例五、测试和验证六、总结 在数据库管理中,经常会遇到需要对多个表进行联合更新的情况。这种操作带来了一定的复杂性,因为要确保在整个更新过程中数据…...
数据结构-线性表的应用
目录 前言一、有序表的合并1.1 顺序表实现1.2 单链表实现 二、稀疏多项式的相加和相乘2.1 稀疏多项式的相加2.2 稀疏多项式的相乘 总结 前言 本篇文章介绍线性表的应用,分别使用顺序表和单链表实现有序表的合并,最后介绍如何使用单链表实现两个稀疏多项…...
cpp http server/client
httplib 使用httplib库 basedemo server.cpp #include "httplib.h" #include <iostream> using namespace httplib;int main(void) {Server svr;svr.Get("/hello", [](const Request& req, Response& res) {std::cout << "lo…...

昇思25天学习打卡营第2天|MindSpore快速入门
打卡 目录 打卡 快速入门案例:minist图像数据识别任务 案例任务说明 流程 1 加载并处理数据集 2 模型网络构建与定义 3 模型约束定义 4 模型训练 5 模型保存 6 模型推理 相关参考文档入门理解 MindSpore数据处理引擎 模型网络参数初始化 模型优化器 …...

django之url路径
方式一:path 语法:<<转换器类型:自定义>> 作用:若转换器类型匹配到对应类型的数据,则将数据按照关键字传参的方式传递给视图函数 类型: str: 匹配除了”/“之外的非空字符串。 /test/zvxint: 匹配0或任何…...

【OnlyOffice】桌面应用编辑器,插件开发大赛,等你来挑战
OnlyOffice,桌面应用编辑器,最近版本已从8.0升级到了8.1 从PDF、Word、Excel、PPT等全面进行了升级。随着AI应用持续的火热,OnlyOffice也在不断推出AI相关插件。 因此,在此给大家推荐一下OnlyOffice本次的插件开发大赛。 详细信息…...

[学习笔记]SQL学习笔记(连载中。。。)
学习视频:【数据库】SQL 3小时快速入门 #数据库教程 #SQL教程 #MySQL教程 #database#Python连接数据库 目录 1.SQL的基础知识1.1.表(table)和键(key)1.2.外键、联合主键 2.MySQL安装(略,请自行参考视频)3.基本的MySQL语法3.1.规…...

Buuctf之SimpleRev做法
首先,查个壳,64bit,那就丢进ida64中进行反编译进来之后,我们进入main函数,发现里面没什么东西,那就shiftf12搜索字符串,找到关键字符串,双击进入然后再选中该字符串,ctrl…...

【云原生监控】Prometheus 普罗米修斯从搭建到使用详解
目录 一、前言 二、服务监控概述 2.1 什么是微服务监控 2.2 微服务监控指标 2.3 微服务监控工具 三、Prometheus概述 3.1 Prometheus是什么 3.2 Prometheus 特点 3.3 Prometheus 架构图 3.3.1 Prometheus核心组件 3.3.2 Prometheus 工作流程 3.4 Prometheus 应用场景…...

【C++】模板进阶--保姆级解析(什么是非类型模板参数?什么是模板的特化?模板的特化如何应用?)
目录 一、前言 二、什么是C模板? 💦泛型编程的思想 💦C模板的分类 三、非类型模板参数 ⚡问题引入⚡ ⚡非类型模板参数的使用⚡ 🔥非类型模板参数的定义 🔥非类型模板参数的两种类型 ὒ…...

Cookie与Session
Cookie Set-Cookie: sessionIdabc123; ExpiresWed, 09 Jun 2024 10:18:14 GMT; Path/; Secure; HttpOnlySession session作用域 首先需要了解servlet容器可能包含多个web应用。 在servlet容器中同一应用的servlet 对 session数据是可见的,不同应用之间session是相互…...

Nuxt3 的生命周期和钩子函数(十一)
title: Nuxt3 的生命周期和钩子函数(十一) date: 2024/7/5 updated: 2024/7/5 author: cmdragon excerpt: 摘要:本文详细介绍了Nuxt3中几个关键的生命周期钩子和它们的使用方法,包括webpack:done用于Webpack编译完成后执行操作…...

Windows ipconfig命令详解,Windows查看IP地址信息
「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 ipconfig 1、基…...

在C#/Net中使用Mqtt
net中MQTT的应用场景 c#常用来开发上位机程序,或者其他一些跟设备打交道比较多的系统,所以会经常作为拥有数据的终端,可以用来采集上传数据,而MQTT也是物联网常用的协议,所以下面介绍在C#开发中使用MQTT。 安装MQTTn…...

VBA提取word表格内容到excel
这是一段提取word表格中部分内容的vb代码。 Sub 提取word表格() mypath ThisWorkbook.Path & "\"myname Dir(mypath & "*.doc*")n 4 index of rowsRange("A1:F1") Array("课程代码", "课程名称", "专业&…...

html+css+js图片手动轮播
源代码在界面图片后面 轮播演示用的几张图片是Bing上的,直接用的几张图片的URL,谁加载可能需要等一下,现实中替换成自己的图片即可 关注一下点个赞吧😄 谢谢大佬 界面图片 源代码 <!DOCTYPE html> <html lang&quo…...

【十三】图解 Spring 核心数据结构:BeanDefinition 其二
图解 Spring 核心数据结构:BeanDefinition 其二 概述 前面写过一篇相关文章作为开篇介绍了一下BeanDefinition,本篇将深入细节来向读者展示BeanDefinition的设计,让我们一起来揭开日常开发中使用的bean的神秘面纱,深入细节透彻理解…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...