分布式文件系统 SpringBoot+FastDFS+Vue.js【四】

分布式文件系统 SpringBoot+FastDFS+Vue.js【四】

  • 八、文件的下载和删除功能
    • 8.1.FastDFSClient.java
    • 8.2.FileServerController.java
    • 8.3.Vue的fast.js
    • 8.4.fastdfsimg.vue
    • 8.5.效果
  • 九、总结
  • endl

八、文件的下载和删除功能

8.1.FastDFSClient.java

@Slf4j
public class FastDFSClient {

    static {
        //加载fastDFS客户端的配置文件
        try {
            ClientGlobal.initByProperties("config/fastdfs-client.properties");
            log.info("network_timeout = {} ms", ClientGlobal.g_network_timeout);
            log.info("charset= {}", ClientGlobal.g_charset);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @param fastDFSFile
     * @return
     * @throws IOException
     */
    public static FastDfsFile upload(MultipartFile file, FastDfsFile fastDFSFile) throws IOException {
        byte[] file_buff = null;
        //把文件转成输入流
        InputStream inputStream = file.getInputStream();
        if (inputStream != null) {
            //获取输入流中可读取的数据大小
            int len = inputStream.available();
            //创建足够大的缓冲区
            file_buff = new byte[len];
            //一次性把输入流中的数据全都读入到缓冲区file_buff,那file_buff就要足够大,占用内存也会很大
            inputStream.read(file_buff);
        }
        //关闭输入流
        inputStream.close();

        //通过fastDSF的client代码访问tracker和storage
        try {
            //创建tracker的客户端
            TrackerClient trackerClient = new TrackerClient(ClientGlobal.getG_tracker_group());
            //通过TrackerClient对象获取TrackerServer信息
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;

            //定义storage的客户端,建立与Storage服务器的连接
            StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

            //文件元信息
            NameValuePair[] metaList = new NameValuePair[1];
            metaList[0] = new NameValuePair("fileName", fastDFSFile.getFileName());

            //执行上传
            String fileId = storageClient.upload_file1(file_buff, fastDFSFile.getExt(), metaList);
            log.info("upload success. file id is: {}", fileId);
            fastDFSFile.setFileId(fileId);
            fastDFSFile.setFilePath(fileId);
            fastDFSFile.setFileSize(file.getSize());
            fastDFSFile.setCreateTime(LocalDateTime.now());
            fastDFSFile.setUpdateTime(LocalDateTime.now());
            //通过调用service及dao将文件的路径存储到数据库中

            //关闭storage客户端
            storageClient.close();
            return fastDFSFile;
        } catch (Exception e) {
            log.error("上传文件失败:", e);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     *
     * @param file_id
     * @return
     * @throws IOException
     * @throws MyException
     */
    public static Boolean delete(String file_id) throws IOException, MyException {
        //通过fastDSF的client代码访问tracker和storage
        //创建tracker的客户端
        TrackerClient trackerClient = new TrackerClient(ClientGlobal.getG_tracker_group());
        //通过TrackerClient对象获取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getTrackerServer();
        StorageServer storageServer = null;

        //定义storage的客户端,建立与Storage服务器的连接
        StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

        //查询文件
        //upload success. file id is: group1/M00/00/00/wKjljWXHAauARHa2AAWwwNOt0hY257.png
        String[] splitStr = file_id.split("/");
        String group_name = splitStr[0];//group1
        String remoteFileName = "";//M00/00/00/wKjljWXHAauARHa2AAWwwNOt0hY257.png
        for (int i = 1; i < splitStr.length; i++) {
            remoteFileName += splitStr[i];
            if (i != splitStr.length - 1) {
                remoteFileName += "/";
            }
        }
        log.info("group_name : {}", group_name);
        log.info("remoteFileName : {}", remoteFileName);
        FileInfo fileInfo = storageClient.query_file_info(group_name, remoteFileName);
        log.info("fileInfo = {}", fileInfo);

        if (fileInfo == null) {
            log.info("您删除的文件信息不存在,请核对后再次删除......");
            return false;
        }

        storageClient.delete_file1(file_id);
        log.info("删除成功");

        //关闭storage客户端
        storageClient.close();
        return true;
    }

    /**
     * 下载文件
     *
     * @param file_id
     * @throws IOException
     * @throws MyException
     */
    public static byte[] downloadFastFile(String file_id) throws IOException, MyException {
        //通过fastDSF的client代码访问tracker和storage
        //创建tracker的客户端
        TrackerClient trackerClient = new TrackerClient(ClientGlobal.getG_tracker_group());
        //通过TrackerClient对象获取TrackerServer信息
        TrackerServer trackerServer = trackerClient.getTrackerServer();
        StorageServer storageServer = null;

        //定义storage的客户端,建立与Storage服务器的连接
        StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

        //查询文件
        //upload success. file id is: group1/M00/00/00/wKjljWXHAauARHa2AAWwwNOt0hY257.png
        String[] splitStr = file_id.split("/");
        String group_name = splitStr[0];//group1
        String remoteFileName = "";//M00/00/00/wKjljWXHAauARHa2AAWwwNOt0hY257.png
        for (int i = 1; i < splitStr.length; i++) {
            remoteFileName += splitStr[i];
            if (i != splitStr.length - 1) {
                remoteFileName += "/";
            }
        }
        log.info("group_name : {}", group_name);
        log.info("remoteFileName : {}", remoteFileName);
        FileInfo fileInfo = storageClient.query_file_info(group_name, remoteFileName);
        log.info("fileInfo = {}", fileInfo);

        if (fileInfo == null) {
            log.info("您下载的文件信息不存在,请核对后再次下载......");
            return null;
        }

        //下载操作,传文件id返回字节流
        byte[] bytes = storageClient.download_file1(file_id);

        //关闭storage客户端
        storageClient.close();
        return bytes;
    }
}

8.2.FileServerController.java

@Slf4j
@RestController
@RequestMapping("/fastDFSFile")
public class FileServerController {

    @Resource
    private FastDfsFileService fastDfsFileService;

    @Resource
    private FastDfsFileTypeService fastDfsFileTypeService;

    @PostMapping("/upload")
    @ResponseBody
    public R upload(@RequestParam("file") MultipartFile file) throws IOException {
        //将文件先存储在web服务器上(本机),在调用fastDFS的client将文件上传到 fastDFS服务器
        FastDfsFile fastDFSFile = new FastDfsFile();

        String contentType = file.getContentType();
        //检验当前文件是否在上述集合中
        log.info("上传的文件类型为:{}", contentType);
        int count = fastDfsFileTypeService.selectByFileType(contentType);
        if (count < 1) {
            log.info("不支持此文件类型上传 : {}", contentType);
            return R.error().setCode(208).setMessage("不支持此文件类型上传 : " + contentType);
        }
        log.info("此文件类型为 : {}", contentType);
        fastDFSFile.setFileType(contentType);

        //文件原始名称
        String originalFilename = file.getOriginalFilename();
        log.info("原始文件名称 : {}", originalFilename);
        fastDFSFile.setFileName(originalFilename);

        //文件扩展名比如22.jpg
        String filenameExtension = StringUtils.getFilenameExtension(originalFilename);
        log.info("文件类型 = {}", filenameExtension);//jpg
        if (filenameExtension == null) {
            return R.error().setCode(208).setMessage("此文件没有文件扩展名");
        }
        fastDFSFile.setExt(filenameExtension);

        //新文件名称
        String fileName = UUID.randomUUID().toString().replace("-", "") + "." + filenameExtension;
        log.info("新文件名称 = {}", fileName);

        FastDfsFile fastDfsFile1 = FastDFSClient.upload(file, fastDFSFile);
        if (fastDfsFile1 != null) {
            fastDfsFileService.save(fastDfsFile1);
            Long id = fastDfsFileService.selectByFileId(fastDfsFile1.getFileId());
            fastDfsFile1.setId(id);
            return R.ok().setCode(200).setMessage("上传成功").data("fastDfsFile", fastDfsFile1);
        }
        return R.error().setCode(208).setMessage("上传失败");
    }

    //restful风格
    @DeleteMapping()
    public R delete(@RequestParam("id") Long id, @RequestParam("fileId") String fileId) throws MyException, IOException {
        Boolean result = FastDFSClient.delete(fileId);
        if (!result) {
            log.info("删除失败");
            return R.error().setCode(208).setMessage("删除失败");
        }
        int count = fastDfsFileService.deleteFastDfsFileById(id);
        if (count < 1) {
            log.info("删除失败");
            return R.error().setCode(208).setMessage("删除失败");
        }
        log.info("删除成功");
        return R.ok().setCode(200).setMessage("删除成功");
    }

    @GetMapping()
    public void downloadfile(HttpServletResponse response, String fileId, String fileName) throws IOException, MyException {
        if (fileId == null) return;
        log.info("fileName = {}", fileName);

        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 = FastDFSClient.downloadFastFile(fileId);
        FileInputStream fis = null;
        log.info("fileId = {}", fileId);

        int len = 0;
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            if (bytes == null) {
                return;
            }
            log.info("success");
            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);
            }
        }
    }

    @GetMapping("/getPageFastImg/{page}/{limit}")
    public R getPageFastImg(@PathVariable int page, @PathVariable int limit) {
        PageBean<FastDfsFile> pageBean = fastDfsFileService.findFastDfsFileByPage(page, limit);
        return R.ok().setCode(200).setMessage("查询成功").data("pageBean", pageBean);
    }
}

8.3.Vue的fast.js

import request from "../../utils/request";

const api_name = '/fastDFSFile'

export default {
  //上传图片
  uploadImg() {
    return request({
      url: `${api_name}`,
      method: 'post',
    })
  },
  getPageFastImg(page, limit) {
    return request({
      url: `${api_name}/getPageFastImg/${page}/${limit}`,
      method: 'get',
    })
  },
  getNextPageFastImg(page, limit) {
    return request({
      url: `${api_name}/getPageFastImg/${page}/${limit}`,
      method: 'get',
    })
  },
  //restful风格 ?id=123&fileId=456
  deleteFastImg(id, fileId) {
    return request({
      url: `${api_name}`,
      method: 'delete',
      params: {
        "id": id,
        "fileId": fileId
      }
    })
  },
  getFileSrc(fileId) {
    return request({
      url: `${api_name}`,
      method: 'get',
      params: {
        "fileId": fileId
      },
      responseType: 'blod'
    })
  },
}

8.4.fastdfsimg.vue

<template>
  <div>
    <h2>图片管理</h2>
    <!--图片列表-->
    <el-table
      size="small"
      style="margin: 30px;"
      empty-text="无数据"
      :data="imgList"
      highlight-current-row v-loading="loading" border element-loading-text="拼命加载中">
      <el-table-column align="center" sortable prop="filePath" label="文件路径" width="450"></el-table-column>
      <el-table-column align="center" sortable prop="fileSize" label="文件大小" width="100"></el-table-column>
      <el-table-column align="center" sortable prop="fileName" label="文件名" width="130"></el-table-column>
      <el-table-column align="center" sortable prop="ext" label="扩展名" width="100"></el-table-column>
      <el-table-column align="center" sortable prop="fileType" label="文件类型" width="100"></el-table-column>
      <el-table-column align="center" sortable prop="filePath" label="预览图片" width="100">
        <template slot-scope="scope">
          <img :src="getImageUrl(scope.row.filePath)" style="max-width: 100px;max-height: 100px" alt="图标"/>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button type="text" size="small" icon="el-icon-download" @click="getFileSrc(scope.row)">下载</el-button>
          <el-popconfirm title="确定删除吗?" @confirm="handleDeleteOne(scope.row)">
            <template #reference>
              <el-button type="danger" size="small" icon="el-icon-delete">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <el-pagination class="pagination" style="text-align: center;margin-top: 50px"
                   layout="prev, pager, next"
                   :current-page="page"
                   :total="total"
                   :page-size="limit"
                   @current-change="fetchData">
    </el-pagination>
  </div>
</template>

<script>
import fastApi from "@/api/fastdfs/fast";
import request from "../../utils/request";

export default {
  name: "FastdfsImg",
  data() {
    return {
      total: 0, // 数据库中的总记录数
      page: 1, // 默认页码
      limit: 5, // 每页记录数

      imgList: {},
      //imagePath: 'http://192.168.229.141/', // 图片的基础路径
    }
  },
  created() {
    this.init()
  },
  methods: {
    init() {
      fastApi.getPageFastImg(this.page, this.limit).then(response => {
        this.imgList = response.data.pageBean.lists
        this.total = response.data.pageBean.totalCount
      })
    },

    //获取图片路径
    getImageUrl(filePath) {
      //return `${this.imagePath}${filePath}`; // 拼接图片路径
      return this.$baseImagePath + '/' + filePath; // 拼接图片路径
    },

    //下一页
    fetchData(page) {
      this.page = page
      fastApi.getNextPageFastImg(this.page, this.limit).then(response => {
        this.imgList = response.data.pageBean.lists
        this.total = response.data.pageBean.totalCount
      })
    },

    // 单选删除
    handleDeleteOne(FastDfsFile) {
      fastApi.deleteFastImg(FastDfsFile.id, FastDfsFile.fileId).then(response => {
        this.$message.success(response.message)
        this.init()
      })
    },

    // 下载文件
    getFileSrc(FastDfsFile) {
      //window.open(this.$baseImagePath+'/'+FastDfsFile.fileId,"_blank");
      /*fastApi.downloadFastImg(FastDfsFile.fileId).then(response=>{
        this.$message.success(response.message)
      })*/
      window.location.href = request.defaults.baseURL + '/fastDFSFile?fileId=' + FastDfsFile.fileId + '&&fileName=' + FastDfsFile.fileName;
    }

  },
}
</script>

<style scoped>

</style>

8.5.效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

九、总结

  • 案例有些不足
  • 功能太简单
  • 功能复杂可以做一个类似网盘的文件管理系统
  • 仅仅学习使用某些功能
  • 暂不深入开发
  • 有兴趣的伙伴可以尝试一番
  • 类似于阿里云oss

endl

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

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

相关文章

websocket数据帧格式

客户端、服务端数据的交换&#xff0c;离不开数据帧格式的定义。因此&#xff0c;在实际讲解数据交换之前&#xff0c;我们先来看下WebSocket的数据帧格式。 WebSocket客户端、服务端通信的最小单位是帧&#xff08;frame&#xff09;&#xff0c;由1个或多个帧组成一条完整的消…

Atcoder ABC339 C - Perfect Bus

Perfect Bus&#xff08;完美的公交车&#xff09; 时间限制&#xff1a;2s 内存限制&#xff1a;1024MB 【原题地址】 所有图片源自Atcoder&#xff0c;题目译文源自脚本Atcoder Better! 点击此处跳转至原题 【问题描述】 【输入格式】 【输出格式】 【样例1】 【样例输…

排序算法---计数排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 计数排序&#xff08;Counting Sort&#xff09;是一种线性时间复杂度的排序算法&#xff0c;其核心思想是通过统计待排序元素的个数来确定元素的相对位置&#xff0c;从而实现排序。 具体的计数排序算法步骤如下&#xff…

Netty Review - 直接内存的应用及源码分析

文章目录 Pre概述应用访问效率&#xff1a; 堆内存 VS 直接内存申请效率&#xff1a; 堆内存 VS 直接内存数据存储结构&#xff1a; 堆内存 VS 直接内存结论 ByteBuffer.allocateDirect 源码分析unsafe.allocateMemory(size) ---> C方法 JVM参数 -XX:MaxDirectMemorySize直接…

视觉slam十四讲学习笔记(五)非线性优化

已经知道&#xff0c;方程中的位姿可以由变换矩阵来描述&#xff0c;然后用李代数进行优化。观测方程由相机成像模型给出&#xff0c;其中内参是随相机固定的&#xff0c;而外参则是相机的位姿。 目录 前言 一、状态估计问题 1 最大后验与最大似然 2 最小二乘的引出 二、非…

JavaScript中null和undefined的区别

JavaScript中null和undefined是两个特殊的值&#xff0c;经常在编程中遇到。虽然它们经常被混淆&#xff0c;但它们有着不同的含义和用法。本文将详细介绍JavaScript中null和undefined的区别&#xff0c;帮助开发者更好地理解和使用它们。 首先&#xff0c;让我们来了解一下nu…

css篇---移动端适配的方案有哪几种

移动端适配 移动端适配是指同一个页面可以在不同的移动端设备上都有合理的布局。主流实现的方案有 响应式布局通过rem或者vw,vh 等实现不同设备有相同的比例而实现适配 首先需要了解viewport 【视口】 视口代表了一个可看见的多边形区域&#xff08;通常来说是矩形&#xff0…

函数递归与迭代附n的阶乘+顺序打印一个整数的每一位数+求第n个斐波那契数

1. 什么是递归&#xff1f; 递归其实是一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是函数自己调用自己。 下面是一个最简单的C语言递归代码&#xff1a; #include <stdio.h> int main() {printf("hehe\n");main();//main函数中⼜调⽤了main函数…

BBC英式口语~发音练习~笔记整理

参考资料 原视频地址&#xff1a; https://www.bilibili.com/video/BV1D7411n7bS/?spm_id_from333.1245.0.0&vd_source5986fc7c8e6d754f3ca44233573aeaff 笔记图片

2.11题目

#include <stdio.h> int main() { char a; while((a getchar()) ! -1) { if(a > A && a < Z) a32; putchar(ch); } return 0;} ———————————————— 版权声明&#xff1a;本文为博主原创文章…

阿里云/腾讯云幻兽帕鲁服务器据点最大帕鲁工作数量最多15个,改成20不生效?

例如&#xff0c;在阿里云的计算巢管理中&#xff0c;找到你的这台部署幻兽帕鲁的服务器实例&#xff0c;选择右上角的“修改游戏配置” 然后选择“基地内工作帕鲁的最大数量”改成20 有人说更改上面的数字&#xff0c;根本不起作用。原因可能如下&#xff1a; 参考资料&#…

css篇---分辨率物理像素和逻辑像素

物理分辨率和逻辑分辨率 物理分辨率是生产屏幕时就固定的&#xff0c;它是不可改变的 -----电脑像素 逻辑分辨率是由软件决定的 【电脑的设置中可以修改分辨率】----css像素 设备像素比 dpr同一方向上的物理像素/css像素 &#xff08;缩放比是1的情况&#xff09; 假设dpr4/…

网络安全最典型基础靶场-DVWA-本地搭建与初始化

写在前面&#xff1a; 之前也打过这个 DVWA 靶场&#xff0c;但是是在虚拟机环境下的一个小块分区靶场&#xff1b; 本篇博客主要介绍在本地搭建 DVWA 靶场以及靶场的初始化&#xff0c;后续会陆续更新通关教程。 由于我们是在本地搭建&#xff0c;则需要基于你已经装好 phpstu…

cefsharp121(cef121.3.7Chromium121.0.6167.160)升级测试及其他H264版本

一、版本说明 1.1 本此版本 此版本CEF 121.3.7+g82c7c57+chromium-121.0.6167.160 / Chromium 121.0.6167.160 1.2 其他支持H264版本 支持H264推荐版本:V100,V109,V111,V119版本,其他V114,V115,V108,V107 支持win7/win8/win8.1最后版本v109.x 支持NET4.5.2最后版本v114.x …

一览大模型长文本能力

前言 如今的大模型被应用在各个场景&#xff0c;其中有些场景则需要模型能够支持处理较长文本的能力(比如8k甚至更长)&#xff0c;其中已经有很多开源或者闭源模型具备该能力比如GPT4、Baichuan2-192K等等。 那关于LLM的长文本能力&#xff0c;目前业界通常都是怎么做的&…

STM32 寄存器操作 GPIO 与下降沿中断

一、如何使用stm32寄存器点灯&#xff1f; 1.1 寄存器映射表 寄存器本质就是一个开关&#xff0c;当我们把芯片寄存器配置指定的状态时即可使用芯片的硬件能力。 寄存器映射表则是开关的地址说明。对于我们希望点亮 GPIO_B 的一个灯来说&#xff0c;需要关注以下的两个寄存器…

leetcode hot100不同路径

本题可以采用动态规划来解决。还是按照五部曲来做 确定dp数组&#xff1a;dp[i][j]表示走到&#xff08;i&#xff0c;j&#xff09;有多少种路径 确定递推公式&#xff1a;我们这里&#xff0c;只有两个移动方向&#xff0c;比如说我移动到&#xff08;i&#xff0c;j&#x…

【机器学习】数据清洗之识别重复点

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…

React入门到精通:掌握前端开发的必备技能!

介绍&#xff1a;React是一个由Facebook开发和维护的JavaScript库&#xff0c;用于构建用户界面&#xff0c;特别是用于构建单页应用程序和移动应用程序的用户界面。以下是对React的详细介绍&#xff1a; 虚拟DOM&#xff1a;React通过使用虚拟DOM&#xff08;Document Object …

Rust 数据结构与算法:3栈:用栈实现符号匹配

1、符号匹配 如&#xff1a; (56)(78)/(43)、{ { ( [ ] [ ])}}、(ab)(c*d)func() 等各类语句的符号匹配。 这里我们关注的不是数字而是括号&#xff0c;因为括号更改了操作优先级&#xff0c;限定了语言的语义&#xff0c;这是非常重要的。如果括号不完整&#xff0c;那么整个…