基于若依的文件上传、下载

基于若依实现文件上传、下载

文章目录

  • 基于若依实现文件上传、下载
    • 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 clearable
            v-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/uploadPath
            String 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-upload
            class="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)
          //拿到后端响应的文件名称反显到列表的form
          this.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/uploadPath
            String 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)
    @PostMapping
    public 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.originalFilename
          this.form.filePath = res.fileName
        })
    },

加上下载按钮

 <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['system:book:edit']"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['system:book:remove']"
          >删除</el-button>
          <el-button
            size="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

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

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

相关文章

kafka系列之消费后不提交offset情况的分析总结

概述 每当我们调用Kafka的poll()方法或者使用KafkaListener(其实底层也是poll()方法)时&#xff0c;它都会返回之前被写入Kafka的记录&#xff0c;即我们组中的消费者还没有读过的记录。 这意味着我们有一种方法可以跟踪该组消费者读取过的记录。 如前所述&#xff0c;Kafka的一…

一种一维时间序列信号变化/事件/异常检测方法(MATLAB)

随着工业物联网、大数据和人工智能的发展&#xff0c;传统工业正在向数字化和智能化升级&#xff0c;从而创造了大量的时间序列数据。通过分析这些数据&#xff0c;可以提供准确可靠的信息服务和决策依据&#xff0c;促进制造业的转型升级。工业物联网在传统工业向“工业 4.0”…

CASS如何输入距离和坐标绘制图形

1、软件版本 这里使用CASS7.0软件进行操作。如下&#xff1a; 2、 操作 输入&#xff1a;500,45【表示距离500米&#xff0c;方向45度】。 点击回车&#xff0c;完成绘制。

V3.76 ViVaCut高级版本!已经开启永久订阅!一款专业视频剪辑软件

在短视频和社交媒体盛行的今天&#xff0c;视频内容的创作和分享已经成为人们日常生活的一部分。为了满足广大视频创作者的需求&#xff0c;一款专业视频剪辑软件应运而生&#xff0c;以其强大的功能和用户友好的界面&#xff0c;为用户提供了全新的视频编辑体验。他提供了众多…

JWT(Json Web Token)在.NET Core中的使用

登录成功时生成JWT字符串目录 JWT是什么&#xff1f; JWT的优点&#xff1a; JWT在.NET Core 中的使用 JWT是什么&#xff1f; JWT把登录信息&#xff08;也称作令牌&#xff09;保存在客户端为了防止客户端的数据造假&#xff0c;保存在客户端的令牌经过了签名处理&#xf…

TikTok马来西亚直播网络怎么配置?

TikTok是一款全球流行的社交媒体应用&#xff0c;在东南亚地区拥有大量用户。在马来西亚这个多元化的国家&#xff0c;配置高效稳定的直播网络对TikTok的运营至关重要。 配置马来西亚直播网络的必要性 广泛的地理覆盖&#xff1a;马来西亚包括大片陆地和众多岛屿&#xff0c;网…

加入运动健康数据开放平台,共赢鸿蒙未来

HarmonyOS SDK运动健康服务&#xff08;Health Service Kit&#xff09;是为华为生态应用打造的基于华为帐号和用户授权的运动健康数据开放平台。在获取用户授权后&#xff0c;开发者可以使用运动健康服务提供的开放能力获取运动健康数据&#xff0c;基于多种类型数据构建运动健…

大数据Spark 面经

1: Spark 整体架构 Spark 是新一代的大数据处理引擎&#xff0c;支持批处理和流处理&#xff0c;也还支持各种机器学习和图计算&#xff0c;它就是一个Master-worker 架构&#xff0c;所以整个的架构就如下所示&#xff1a; 2: Spark 任务提交命令 一般我们使用shell 命令提…

理解MySQL核心技术:存储过程与函数的强大功能

在大型应用程序和复杂的数据库操作中&#xff0c;存储过程与函数扮演着至关重要的角色。它们不仅可以提高代码的可维护性&#xff0c;还能加强数据库的安全性和性能。本篇文章将深入探讨MySQL存储过程与函数的基础知识、创建、管理及其在实际应用中的优势。 什么是存储过程和函…

set的应用(C++)

set的使用 【基本用法】 大家可以敲一下这段代码体会一下set的基本初始化和使用 #include <iostream> #include <set> #include <vector> using namespace std;int main() {set<int> st1; // 空的set// 使用迭代器构造string str("abcdef"…

uniapp实现一个键盘功能

前言 因为公司需要&#xff0c;所以我.... 演示 代码 键盘组件代码 <template><view class"keyboard_container"><view class"li" v-for"(item, index) in arr" :key"index" click"changArr(item)" :sty…

【GIt】变基(rebase)

目录 变基(rebase)是什么为什么有变基变基后的时间线变基前的时间线 变基原理怎么变基同一个分支变基不同分支变基 参考文章 变基(rebase)是什么 Git 变基&#xff08;rebase&#xff09;是一种用于整合分支的方法&#xff0c;它的工作原理是将一系列提交&#xff08;或分支合…

Pycharm远程连接GPU(内容:下载安装Pycharm、GPU租借、配置SSH、将代码同步到镜像、命令行操控远程镜像、配置远程GPU解释器)

目录 windows下载安装pycharmGPU租借网站AutoDlfeaturize好易智算 GPU租借GPU选择选择镜像充值 然后创建镜像创建成功 复制SSH登录信息 远程进入镜像 在Pycharm中进行ssh连接新建SFTP配置SSH复制ssh根据复制的信息填写ssh配置测试连接 将代码同步到远程镜像上设置mappings将本地…

XAML 框架横向对比

多年来&#xff0c;基于 XAML 的 UI 框架有了很大的发展。下面的图表很好地证明了这个观点。XAML UI 框架的三大巨头&#xff1a;Avalonia UI、Uno Platform 和 .NET MAUI 都支持跨平台的应用。事实上&#xff0c;除了 Avalonia UI&#xff0c;对跨平台 XAML 的需求是它们发展的…

Mysql部署MHA高可用

部署前准备&#xff1a; mysql-8.0.27下载地址&#xff1a;https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar mha-manager下载地址&#xff1a;https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-mana…

三丰云评测:免费虚拟主机与免费云服务器的全面对比

三丰云是一家知名的互联网服务提供商&#xff0c;专注于虚拟主机和云服务器的服务。在互联网技术日新月异的今天&#xff0c;选择一个优质的云服务提供商至关重要。本次评测将重点对比三丰云的免费虚拟主机和免费云服务器&#xff0c;帮助用户更好地选择适合自己需求的服务。首…

Java基础-接口与实现

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 Java 接口 什么是接口&#xff1f; 声明接口 实现接口 继承接口 接口的多继承 标记接口 Java 接口 …

【海贼王的数据航海】ST表——RMQ问题

目录 1 -> RMQ问题 1.1 -> 定义 1.2 -> 解决策略 2 -> ST表 2.1 -> 定义 2.2 什么是可重复贡献问题 2.3 -> 预处理ST表 2.4 -> 处理查询 2.5 -> 实际问题 1 -> RMQ问题 1.1 -> 定义 RMQ (Range Minimum/Maximum Query)即区间最值查询…

Qwen1.5-1.8b部署

仿照ChatGLM3部署&#xff0c;参考了Qwen模型的文档&#xff0c;模型地址https://modelscope.cn/models/qwen/Qwen1.5-1.8B-Chat/summary http接口 服务端代码api.py from fastapi import FastAPI, Request from transformers import AutoTokenizer, AutoModelForCausalLM, …

BitWidget,自定义bit控件

由于QBitArray并不满足我做界面是的需求&#xff0c;所以参照QBitArray简单的写了个控件&#xff0c;如下所示&#xff0c;源码及实例在我上传的资源包中 实例 帮助文档如图所示&#xff08;部分&#xff09; 帮助文档&#xff08;在资源包中&#xff09; 1.html文档 2.chm文…