记录springboot+vue+fastdfs实现简易的文件(上传、下载、删除、预览)操作

2023-11-04

前言说明springboot + vue + FastDFS实现文件上传(支持预览)升级版

FASTDFS部分

FASTDFS安装过程:基于centos 7安装FastDFS文件服务器

SpringBoot部分

springboot源码实现

package com.core.doc.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.core.doc.entity.FileInfo;
import com.core.doc.mapper.FileInfoMapper;
import com.core.doc.response.Result;
import com.core.doc.until.FastUtils;
//import org.openimaj.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/upload")
@CrossOrigin
public class UploadController {

    @Autowired
    FileInfoMapper fileInfoMapper;


    /**
    * 文件上传
    **/
    @PostMapping("/import")
    public String importData(MultipartFile file, HttpServletRequest req) throws IOException {

        System.out.println("file = " + file);
        String name = file.getOriginalFilename();
        String realPath = req.getSession().getServletContext().getRealPath("/");
        System.out.println("realPath = " + realPath);
        String fileId = FastUtils.upload(file);
//        String url = "http://xx.xx.x.xx/" + fileId;
        String url =  fileId;
        System.out.println(url);
        return url;
    }
    /**
    * 文件下载
    **/
    @GetMapping("/downloadFile")
    public void downloadFile(HttpServletResponse response,String  filePath) throws UnsupportedEncodingException {
//        String filePath = "group1/M00/00/00/wKg4CmP7OiaAUzIvAADA8Mf85m8974.pdf";
//        String fileName = "xxx.pdf";
//        File file = new File(filePath);
//        if(file.exists()) {
        if(filePath == null)return;
        QueryWrapper<FileInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("filePath",filePath);
        List<FileInfo> fileInfos = fileInfoMapper.selectList(wrapper);
        String filename = "未知文档.pdf";
        if(fileInfos != null && fileInfos.size() > 0 && fileInfos.get(0).getFilename() != null ){
            filename = fileInfos.get(0).getFilename() ;
            if(!fileInfos.get(0).getFilename().contains(".pdf")){
                filename = fileInfos.get(0).getFilename() +".pdf";
            }
        }

        response.setContentType("application/force-download;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.addHeader("Content-Disposition", "attachment;fileName="  + new String(filename.getBytes("gb2312"), "ISO-8859-1"));


        byte[] bytes = FastUtils.testDownload(filePath);
        FileInputStream fis = null;
        System.out.println(filePath);


        OutputStream outputStream = null;
        int len = 0;
        try {
            outputStream = response.getOutputStream();
            System.out.println(bytes);
            if(bytes == null){
                return;
            }
            outputStream.write(bytes);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

	 /**
    * 文件删除
    **/
    @PostMapping("/del")
    @ResponseBody
    public Result delFile(@RequestParam String fileName) {
        
        int i = FastUtils.delFile(fileName);
        if(i != -1){
            return Result.ok().data("msg", "删除成功");
        } else {
            return Result.error().data("msg", "失败");
        }
    }


    @PostMapping("/downlaod")
    @ResponseBody
    public byte[] upload(HttpServletResponse response, @RequestParam String fileName) {

        byte[] bytes = FastUtils.testDownload(fileName);
        response.setContentType("application/octet-stream;charset=UTF-8");
// 设置返回的文件类型
        OutputStream toClient = null; // 得到向客户端输出二进制数据的对象
        try {

            response.setCharacterEncoding("UTF-8");
            //使用setHeader方法设置浏览器使用UTF-8进行解码
            response.setHeader("Content-Type", "text/html;charset=UTF-8");
            toClient = response.getOutputStream();

            toClient.write(bytes); // 输出数据
            toClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return bytes;
        }
    }


  

    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"declare.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
//        IOUtils.write(data, (DataOutput) response.getOutputStream());
    }


}

FastUtils工具类

package com.core.doc.until;

import org.csource.common.MyException;
import org.csource.fastdfs.*;
import org.junit.Test;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件上传工具类
 */
public class FastUtils {

    private static StorageClient1 client1;

    static {
        try {
            ClientGlobal.initByProperties("fastdfs-client.properties");
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            client1 = new StorageClient1(trackerServer, null);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

    }


    public static int delFile(String filename) {

        int count = 0;

        try {
            count = client1.delete_file1(filename);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }finally {
            return count;
        }

    }

    public static String upload(MultipartFile file) {
        String oldName = file.getOriginalFilename();

        try {
            return client1.upload_file1(file.getBytes(), oldName.substring(oldName.lastIndexOf(".") + 1), null);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static byte[] download(String filepath, HttpServletResponse response) throws IOException {
        byte[] bytes = null;
        try {
            //1.初始化fastdfs客户端配置文件
            ClientGlobal.initByProperties("fastdfs-client.properties");// 加载properties配置文件
            System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms");//输出properties中配置的参数,检测properties文件是否生效
            System.out.println("charset=" + ClientGlobal.g_charset);

            // 2.获取trackerServer
            TrackerClient tracker = new TrackerClient();// 创建tracker客户端对象
            TrackerServer trackerServer = tracker.getConnection();//获得tracker连接对象

            //3.获取storageClient(通过trackerServer 和 storageServer:null)
            StorageServer storageServer = null;
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);//通过tracker服务器返回storage服务器对象(客户端)
            String name = "wKg4CmP7btCAZpAmAADA8Mf85m8679.pdf";
            //4.下载操作
            //方式一 文件id下载
            bytes = client.download_file1("group1/M00/00/00/wKg4CmP7btCAZpAmAADA8Mf85m8679.pdf");//记得要传文件id返回字节流
            File file=new File("D:\\KM\\"+name);// 给定文件路径 和 名称
            FileOutputStream fileOutputStream=new FileOutputStream(file);//窗机输出流
            fileOutputStream.write(bytes);//写入数据
            fileOutputStream.close();//关闭输出流

            //方式二 组名+文件路径
            byte[] bytes2 = client.download_file("group1","/M00/00/00/"+name);//记得修改
            File file2=new File("D:\\KM\\1"+name);// 给定文件路径 和 名称
            FileOutputStream fileOutputStream2=new FileOutputStream(file2);//窗机输出流
            fileOutputStream2.write(bytes);//写入数据
            fileOutputStream2.close();//关闭输出流

            trackerServer.close();

        } catch (Exception ex) {
            ex.printStackTrace();
        }finally {
            return bytes;
        }
    }



    public static byte[] testDownload(String filename) {
        byte[] bytes = null;
        try {
            //1.初始化fastdfs客户端配置文件
            ClientGlobal.initByProperties("fastdfs-client.properties");// 加载properties配置文件
            System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms");//输出properties中配置的参数,检测properties文件是否生效
            System.out.println("charset=" + ClientGlobal.g_charset);

            // 2.获取trackerServer
            TrackerClient tracker = new TrackerClient();// 创建tracker客户端对象
            TrackerServer trackerServer = tracker.getConnection();//获得tracker连接对象

            //3.获取storageClient(通过trackerServer 和 storageServer:null)
            StorageServer storageServer = null;
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);//通过tracker服务器返回storage服务器对象(客户端)
            String name = "wKg4CmP7btCAZpAmAADA8Mf85m8679.pdf";
            //4.下载操作
            //方式一 文件id下载
             bytes = client.download_file1(filename);//记得要传文件id返回字节流
//            File file=new File("D:\\KM\\"+name);// 给定文件路径 和 名称
//            FileOutputStream fileOutputStream=new FileOutputStream(file);//窗机输出流
//            fileOutputStream.write(bytes);//写入数据
//            fileOutputStream.close();//关闭输出流

            //方式二 组名+文件路径
//            byte[] bytes2 = client.download_file("group1","/M00/00/00/"+name);//记得修改
//            File file2=new File("D:\\KM\\1"+name);// 给定文件路径 和 名称
//            FileOutputStream fileOutputStream2=new FileOutputStream(file2);//窗机输出流
//            fileOutputStream2.write(bytes);//写入数据
//            fileOutputStream2.close();//关闭输出流


            trackerServer.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
            return bytes;
        }
    }



}

Vue部分

vue预览功能参考:vue-pdf实现pdf文件在线预览

vue预览功能结合实现(以下代码为案例代码:核心代码)
一、本地测试环境,需要配置跨域
在vue.config.js中配置需要跨域的IP地址

 'pdf': {
              target: 'http://xxx.xxx.xx.x/',
              changOrigin: true,  
              pathRewrite: {
                  '^/pdf': ''  
              } 
          }

其中 pdfUrl 只需赋值 后缀即可如下所示

group1/M00/00/01/wKg4CmQVuuiAZRYnAALX0oge5B8291.pdf

在这里插入图片描述

 <el-dialog title="查看" :visible.sync="showVisible" :width="hxi+'%'">
           <div class="pdf" :visible.sync="showVisible">
            
                <div class="pdf-tab">
                <!-- <div class="btn-def"
                    @click.stop="clock">顺时针</div>
                <div class="btn-def"
                    @click.stop="counterClock">逆时针</div> -->
                </div>
              
                <el-button type="success" :class="{select:idx==0}"
                        @touchstart="idx=0"
                        @touchend="idx=-1"
                        @click="scaleD">
                放大
               </el-button>
               <el-button type="success" :class="{select:idx==1}"
                        @touchstart="idx=1"
                        @touchend="idx=-1"
                        @click="scaleX">
                缩小
              </el-button>
               
                <!-- <div>进度:{{loadedRatio}}</div> -->
                <!-- <div>页面加载成功: {{curPageNum}}</div> -->
                 <div class="main">
                    <pdf ref="pdf"
                        :src="pdfUrl"
                        :page="pageNum"
                        :rotate="pageRotate"
                        @password="password"
                        @progress="loadedRatio = $event"
                        @page-loaded="pageLoaded($event)"
                        @num-pages="pageTotalNum=$event"
                        @error="pdfError($event)"
                        @link-clicked="page = $event">
                    </pdf>
                     <div style="float:right">{{pageNum}}/{{pageTotalNum}}</div>
                </div> 
                 <div>
                 
                   <el-button class="btn-def btn-pre" type="success"
                        @click.stop="prePage" style="mar">上一页</el-button>
                    <el-button class="btn-def btn-next" type="primary"`在这里插入代码片`
                        @click.stop="nextPage">下一页 </el-button>
                        
                 </div>
              
            </div>
         </el-dialog>

二、若是部署上线,无法预览需要配置nginx进行地址映射,比如部署的tomcat服务器地址为 8080端口,而安装的DFS服务器为80端口,那就将tomcat的8080端口,配置代理为

location /pdf/{
            proxy_pass   http://xxx.xxx.xx.xx:8080/;
 }

在这里插入图片描述

下载功能,目前实现就是结合后端,通过io流的形式,进行跳转下载
,vue处理代码如下:

 window.location.href = 'http://xxx.xxx.xx.xx:8082/upload/downloadFile?filePath='+this.FileData.filepath;

在这里插入图片描述

在这里插入图片描述
文件上传功能,结合 element ui
只需将action 改为自己的接口即可,springboot的源码在上面

<el-upload
  class="upload-demo"
  action="https://localhost:8082/upload/file"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :before-remove="beforeRemove"
  multiple
  :limit="3"
  :on-exceed="handleExceed"
  :file-list="fileList">
  <el-button size="small" type="primary">点击上传</el-button>
  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记录springboot+vue+fastdfs实现简易的文件(上传、下载、删除、预览)操作 的相关文章

  • 策略模式还是命令模式?

    假设我有一个金融交易列表 我需要针对这些交易执行一系列验证规则 一个例子是我有一笔购买产品的交易 但是首先我需要验证交易中的帐户是否有足够的可用资金 产品没有售完等 由于这些规则 交易将是标记为拒绝 并应指定错误代码 当然 我正在考虑用一个
  • 将 MouseListener 添加到面板

    我正在尝试将鼠标操作添加到我的面板中 这就是程序应该做的事情 编写一个程序 允许用户通过按三下鼠标来指定一个三角形 第一次按下鼠标后 画一个小点 第二次按下鼠标后 绘制一条连接前两个点的线 第三次按下鼠标后 绘制整个三角形 第四次按下鼠标会
  • 查询 MongoDB 集合中的字段。

    我正在尝试查询 mongodb 集合中的特定字段 这是我的代码和输出 Mongo m new Mongo DB db m getDB mydb DBCollection coll db getCollection student addin
  • 重写 getPreferredSize() 会破坏 LSP

    我总是在这个压倒一切的网站上看到建议getPreferredSize 而不是使用setPreferredSize 例如 如前面的线程所示 对于固定大小的组件 使用重写 getPreferredSize 而不是使用 setPreferredS
  • 迭代函数可以调用自身吗?

    当观看下面的 MIT 6 001 课程视频时 讲师在 28 00 将此算法标记为迭代 但是 在 30 27 他说这个算法和实际的 递归 算法都是递归的 该函数正在使用基本情况调用自身 那么这次迭代情况如何 private int itera
  • 记录共享和映射的诊断上下文

    据我所知 其他人做了什么来解决 Commons Logging 项目 针对 NET 和 Java 不支持映射或嵌套诊断上下文这一事实 执行摘要 我们选择直接使用实现者日志框架 在我们的例子中为 log4j 长答案 您是否需要一个抽象日志框架
  • 以有效的方式从 Map 中删除多个键?

    我有一个Map
  • 这个等待通知线程语义的真正目的是什么?

    我刚刚遇到一些代码 它使用等待通知构造通过其其他成员方法与类中定义的线程进行通信 有趣的是 获取锁后 同步范围内的所有线程都会在同一锁上进行定时等待 请参见下面的代码片段 随后 在非同步作用域中 线程执行其关键函数 即 做一些有用的事情1
  • JavaFX使节点覆盖父节点边框颜色

    我有一个如下所示的节点 仅使用 css 我希望标签覆盖其父边框颜色 因此标签下方的边框颜色部分变得不可见 我用来制作这个边框的CSS代码 fx border color black fx border width 3 fx border r
  • 在java中将字符串日期转换为美国格式

    我有下面的代码 其中日期为字符串类型 我必须将其设置为美国格式 所以下面我已经展示了它 private static final SimpleDateFormat usOutputDate new SimpleDateFormat MM d
  • 在grails控制器中识别ajax请求或浏览器请求

    我正在开发一个使用大量ajax的grails应用程序 如果请求是ajax调用 那么它应该给出响应 这部分正在工作 但是如果我在浏览器中输入URL 它应该带我到主页 索引页面而不是请求的页面 下面是ajax调用的示例gsp代码
  • 具有 JPA 持久性的 Spring 状态机 - 存储库使用

    我试图弄清楚如何轻松使用 Spring 状态机 包括使用 JPA 进行持久化 这是我正在处理的问题 不兼容的数据类型 工厂和持久性 在程序的某个时刻 我想使用连接到用户的状态机 有用于此目的的存储库 项目spring statemachin
  • 拆分/标记化/扫描字符串并注意引号

    Java中是否有默认 简单的方法来分割字符串 但要注意引号或其他符号 例如 给定以下文本 There s a man that live next door in my neighborhood and he gets me down Ob
  • 如何在不反编译的情况下更改已编译的.class文件?

    我想更改 class 文件方法 我安装 JD Eclipse Decompiler 并打开 class 文件 我添加了一些代码并保存 class 文件 但是 class 文件没有改变 我不知道如何使用反编译器 如果可能的话 如何在不使用反编
  • Java 中 JButton 的击键/热键

    最初我使用 JMenu 并建立热键以使用加速器工作 它运行得很好 现在我想在 JButton 中实现相同的行为 但我陷入困境 这是我编写的代码 请分享您的想法 以便我可以走上正确的道路 import javax swing import j
  • 当底层连接是有状态时如何使用 Apache HttpClient?

    我在谷歌上搜索了很多关于如何使用 HttpClient 进行多线程处理的信息 他们中的大多数人建议使用 ThreadSafeClientConnManager 但我的应用程序必须登录某个主机 登录表单页面 以便 HttpClient 获得底
  • spring data jpa复合键重复键记录插入导致更新

    我有一个具有复合键的实体 我试图通过使用 spring data jpa 存储库到 mysql 数据库来持久化它 如下所示 Embeddable public class MobileVerificationKey implements S
  • Java/MongoDB 按日期查询

    我将一个值作为 java util Date 存储在我的集合中 但是当我查询以获取两个特定日期之间的值时 我最终得到的值超出了范围 这是我的代码 插入 BasicDBObject object new BasicDBObject objec
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使
  • Java中单例的其他方式[重复]

    这个问题在这里已经有答案了 只是我在考虑编写单例类的其他方法 那么这个类是否被认为是单例类呢 public class MyClass static Myclass myclass static myclass new MyClass pr

随机推荐