SpringBoot整合FastDFS笔记

news2024/11/16 12:48:13

SpringBoot整合FastDFS笔记

FastDFS是国人余庆开发的一个的分布式存储系统,github地址是https://github.com/happyfish100/fastdfs

FastDFS的特性:

1、分组存储,灵活简洁、对等结构,不存在单点

2、 文件ID由FastDFS生成,作为文件访问凭证。FastDFS不需要传统的name server

3、和流行的web server无缝衔接,FastDFS已提供apache和nginx扩展模块

4、大、中、小文件均可以很好支持,支持海量小文件存储

5、 支持多块磁盘,支持单盘数据恢复

6、 支持相同文件内容只保存一份,节省存储空间

7、 存储服务器上可以保存文件附加属性

8、 下载文件支持多线程方式,支持断点续传

FastDFS部署教程可以参考
https://www.jb51.net/article/251253.htm

springboot整合fastDFS的物料准备:

1.java项目配置fastdfs

2.定义工具类

3.测试使用效果

java项目配置fastdfs

引入fastdfs-client相关依赖

<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.8</version>
        </dependency>

        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.7</version>
        </dependency>

配置项目yml文件

fdfs:
  so-timeout: 5000 # 读取时间
  connect-timeout: 5000 #连接超时
  # 生成缩略图参数
  thumb-image:
    width: 50
    height: 50
# 支持配置多个存储节点    
  tracker-list:
    - 10.1.5.212:22122

启动类配置

package com.example.demo;
import com.github.tobato.fastdfs.FdfsClientConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@Import({FdfsClientConfig.class,cn.hutool.extra.spring.SpringUtil.class})
@MapperScan(basePackages = {"com.example.demo.orm.dao"})
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

定义fdfs工具类

package com.example.demo.util;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;

@Component
@Slf4j
public class FdfsTools {
    @Autowired
    private FastFileStorageClient fastFileStorageClient;


    /**
     * 文件上传, byte 流类型
     *
     * @param bytes     文件字节
     * @param fileSize  文件大小
     * @param extension 文件扩展名
     * @return fastDfs路径
     */
    public String uploadFile(byte[] bytes, long fileSize, String extension) {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        StorePath storePath = fastFileStorageClient.uploadFile(
                byteArrayInputStream,
                fileSize,
                extension,
                null);
        return storePath.getFullPath();
    }

    /**
     * MultipartFile类型的文件上传ַ
     *
     * @param file
     * @return
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        StorePath storePath = fastFileStorageClient.uploadFile(
                file.getInputStream(),
                file.getSize(),
                FileNameUtil.getSuffix(file.getOriginalFilename()),
                null);
        return storePath.getFullPath();
    }

    /**
     * 普通文件上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    public String uploadFile(File file) throws FileNotFoundException {
        FileInputStream inputStream = new FileInputStream(file);
        StorePath path = fastFileStorageClient.uploadFile(
                inputStream,
                file.length(),
                FileNameUtil.getSuffix(file),
                null);
        return path.getFullPath();
    }


    public String createFileAndUpload(String sourceFilePath) throws Exception {
        File file = new File(sourceFilePath);
        return uploadFile(file);
    }

    /**
     * 带输入流形式的文件上传
     *
     * @param inputStream
     * @param size
     * @param fileName
     * @return
     */
    public String uploadFile(InputStream inputStream, long size, String fileName) {
        StorePath path = fastFileStorageClient.uploadFile(inputStream, size, fileName, null);
        return path.getFullPath();
    }

    /**
     * 将一段文本文件写到fastdfs的服务器上
     *
     * @param content
     * @param fileExtension
     * @return
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(StandardCharsets.UTF_8);
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath path = fastFileStorageClient.uploadFile(stream, buff.length, fileExtension, null);
        return path.getFullPath();
    }

    /**
     * 下载文件
     *
     * @param fileUrl 文件URL
     * @return 文件字节
     */
    public byte[] downloadFile(String fileUrl) {
        String group = fileUrl.substring(0, fileUrl.indexOf("/"));
        String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
        DownloadByteArray downloadByteArray = new DownloadByteArray();
        log.info("fdfs下载文件的group:{}",group);
        log.info("fdfs下载文件的path:{}",path);
        return fastFileStorageClient.downloadFile(group, path, downloadByteArray);
    }

    public void deleteFile(String fileUrl) {
        if (StrUtil.isBlank(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            fastFileStorageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (Exception e) {
            log.error("", e);
        }
    }
}

测试使用效果

package com.example.demo;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.example.demo.util.FdfsTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
public class FdfsTestController {


    @Autowired
    private FdfsTools fdfsTools;

    /**
     * 下载fastdfs里的文件
     * http://localhost:8621/mybatis/download?fullPath=group1/M00/64/AF/CgEF1GSSpkGACiJlAAvqH-Poukk892.jpg
     * @param fullPath
     * @param response
     * @throws IOException
     */
    @GetMapping("/download")
    public void download(@RequestParam String fullPath, HttpServletResponse response) throws IOException {
        byte[] bytes = fdfsTools.downloadFile(fullPath);
        String name = FileNameUtil.getName(fullPath);
        System.out.println(name);
        response.setHeader("Content-Disposition",
                "attachment;filename=" + new String(name.getBytes(), StandardCharsets.ISO_8859_1));
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        ServletOutputStream ops = response.getOutputStream();
        IoUtil.copy(inputStream, ops);
        IoUtil.closeIfPosible(inputStream);
        IoUtil.closeIfPosible(ops);
    }


    /**
     * 前端单文件上传 form-data形式参数, 传1个 MultipartFile类型,参数名file
     * @param multipartFile
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadOne")
    public String upload(@RequestPart("file") MultipartFile multipartFile) throws IOException {
        System.out.println(multipartFile.getOriginalFilename());
        String s = fdfsTools.uploadFile(multipartFile);
        return "fullPath=" + s;
    }

    /**
     * 前端多文件上传  form-data形式参数 传多个MultipartFile类型,参数名随意
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadBatch")
    public List<String> uploadBatch(MultipartHttpServletRequest request) throws IOException {
        List<String> result = new ArrayList<>();
        Map<String, MultipartFile> fileMap = request.getFileMap();
        for (MultipartFile multipartFile : fileMap.values()) {
            if (!multipartFile.isEmpty()){
                System.err.println(multipartFile.getOriginalFilename());
                String s = fdfsTools.uploadFile(multipartFile);
                result.add("fullPath=" +s);
            }
        }
        return result;
    }


    /**
     * 将一段文本文件写到fastdfs的服务器上
     * @param content
     * @return fullPath=group1/M00/64/AF/CgEF1GSSqdGAHrO4AAAAD0mMR3c910.txt
     */
    @PostMapping("/saveTxtToFdfs")
    public String saveTxtToFdfs(@RequestParam String content){
        String s = fdfsTools.uploadFile(content, "txt");
        return "fullPath=" +s;
    }

    /**
     * 删除FastDfs上的文件
     * http://localhost:8621/mybatis/delFile?fullPath=group1/M00/64/AF/CgEF1GSSpnKAY3CiAAvea9v85c0615.jpg
     * @param fullPath
     * @return
     */
    @DeleteMapping("/delFile")
    public String deleteFastDfsFile(@RequestParam String fullPath){
        fdfsTools.deleteFile(fullPath);
        return "ok!";
    }

}

测试上传单个文件
在这里插入图片描述
测试上传多个文件
在这里插入图片描述
测试删除FastDFS里已上传的文件
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSDN 周赛 60 期

CSDN 周赛 60 期 60期体验判断题单选题填空题编程题1、题目名称:贝博士的论文审阅统计2、题目名称:括号匹配小结60期体验 本次体验极差,编程题第一题完全看不懂。 然后就是,成绩极差,选择、判断、填空题一共40分,仅仅拿到了十分。 嗯。。。。请允许我先唱两句“都选C”…

[SWPUCTF 2021 新生赛] jicao

需要将json的值进行get传参&#xff0c;以及将id的值进行post传参 因此可以构造payload get传参&#xff1a;?json{"x":"wllm"} post传参&#xff1a;idwllmNB

Z世代消费者崛起,品牌如何靠吉祥物IP增强商业变现能力?

Z世代人群逐渐成为消费者最大主力军&#xff0c;对品牌而言&#xff0c;抓住Z世代消费者的心&#xff0c;就等于抓住机遇。Z世代的年轻人更趋向于为“兴趣”买单&#xff0c;将商品的使用价值与情感价值逐渐分离&#xff0c;拥抱更多的文化&#xff0c;崇尚个性潮流、喜欢新鲜事…

Linux——进程间通信——命名管道

目录 一.命名管道 1.1定义与区别 1.2命名管道的原理 1.3命名管道的创建 1.4命名管道的实现 Comm.hpp 头文件&#xff1a; Sever.cc代码(该进程是读取数据的)&#xff1a; Client.cc(该进程是写数据的)&#xff1a; 1.4.2案例测试&#xff1a; 重新执行Sever: 1.4.3案例…

如何学习PHP常用函数和内置库? - 易智编译EaseEditing

要学习PHP的常用函数和内置库&#xff0c;可以按照以下步骤进行&#xff1a; 学习PHP基础知识&#xff1a; 首先&#xff0c;掌握PHP的基础语法和核心概念。了解变量、数据类型、操作符、控制流程、函数等基本概念和语法规则。 查阅官方文档&#xff1a; PHP官方文档是学习P…

el-date-picker类型是datetimerange然后时间选择器的时分错位和el-time-picker 组件时分秒样式错位

第一种&#xff1a; 现象&#xff1a; 原因&#xff1a; 当分辨率过小且使用了px转换成vw的插件的话&#xff0c;存在vw的精确度不一致导致出现错位&#xff0c;【不知道不用vw转换插件会不会这样&#xff0c;但是解决方法应该是通用的】 解决方法&#xff1a; 在全局引入一…

高通 P-sensor 阈值调整

阈值效果debug 距离传感器调试基本没有太多工作量&#xff0c;主要根据整机来调整阈值&#xff0c;选择最合适的 P-Sensor 感应效果。高通平台sensor代码主要在modem侧&#xff0c;阈值设置是在AP侧&#xff0c;对应配置文件一般是&#xff1a; vendor/qcom/proprietary/senso…

【博客679】LVS NAT模式与FULLNAT模式原理与配置差别

LVS NAT模式与FULLNAT模式原理与配置差别 注意&#xff1a; LVS NAT模式是LVS原生的一种工作方式&#xff0c;而FULLNAT是在NAT模式下通过配置SNAT来 实现FULLNAT的&#xff0c;而且配合SNAT这部分是靠我们自己来实现的 1、LVS NAT模式原理与特点 NAT模式的数据包请求流程&…

基于matlab使用校准相机拍摄的两张图像中恢复相机运动并重建场景的3D结构(附源码)

一、前言 运动结构 &#xff08;SfM&#xff09; 是从一组 3-D 图像估计场景的 2-D 结构的过程。此示例演示如何从两个图像估计校准相机的姿势&#xff0c;将场景的三维结构重建为未知比例因子&#xff0c;然后通过检测已知大小的对象来恢复实际比例因子。 此示例演示如何从使…

如何开一家真人手办店?

从目前的情况来看&#xff0c;在3D建模这一个行业里&#xff0c;真人手办算是一个不错的风口&#xff0c;之前在圈子里刮起了一阵浪潮。手办大家都接触过&#xff0c;真人手办简单来说就是把以前手办的角色变成了真人&#xff0c;作为礼物和纪念品再合适不过。 许多人对这个新生…

【软件安装】Linux系统中安装Nginx服务器(Ubuntu系统)

这篇文章&#xff0c;主要介绍Linux系统中安装Nginx服务器&#xff08;Ubuntu系统&#xff09;。 目录 一、Linux安装Nginx 1.1、下载nginx安装包 &#xff08;1&#xff09;第一种方式 &#xff08;2&#xff09;第二种方式 1.2、上传nginx压缩包到Linux服务器 1.3、解压…

新项目搞完啦!!!

大家好&#xff0c;我是鱼皮。 经过了 7 场直播&#xff0c;总时长近 20 小时&#xff0c;我在 自己的编程导航 的第 5 个 全程直播开发 的项目 —— 智能 BI 项目&#xff0c;完结啦&#xff01; 我在这里对该项目做一个简单的总结&#xff0c;希望让更多需要它的同学看到&am…

爬虫-爬取Bing词典单词相关数据

主要爬取的数据如图片中的红框所示: 爬取效果如下所示: 具体爬虫代码私我&#xff5e;

Seata 四种模式对比总结

一、前言 通过以下系列章节&#xff1a; docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用…

uniapp中微信小程序不能编译style绑定方法的解决方案

uniapp中动态style问题 这是我的代码设置了根据传参显示不同字体颜色和不同背景色 这两个方法我都写在methods中 methods: {// // 添加不同背景颜色getBackColor(val) {let color "";switch (val[4]) {case 0:color background:${this.colors[0]};break;case 1:col…

Python中的for循环语句及其应用举例(等差数列求和、阶乘、寻找最大值)

Python中的for循环语句及其应用举例(等差数列求和、阶乘、寻找最大值) 在学习任何编程语言的时候&#xff0c;不熟悉判断选择结构和循环结构&#xff0c;就难以发挥计算机优秀的计算能力和提高学习工作效率。本文将重点讲解Python中的for循环语句&#xff0c;并举例等差数列求…

数据分析:2023 最值得投资的 AI 公司榜单

文章目录 1 AI 公司的火爆程度和发展趋势1.1 AI 市场的规模和增长趋势1.2 全球 AI 公司数量和分布情况1.3 我们如何把握 AI 风口&#xff1f; 2 方法一&#xff1a;网络数据采集 - 使用亮数据代理2.1 动态 ip 代理&#xff0c;获取数据2.2 浏览器代理 3 方法二&#xff1a;网络…

Linux:nginx虚拟主机

基于域名 cd /usr/local/nginx/html/ mkdir aaa mkdir bbb echo www.aaa.com > aaa/index.html echo www.bbb.com > bbb/index.html vim /usr/local/nginx/conf/nginx.conf 修改server中的配置 server {listen 80;server_name www.benet.com;charset utf-8;access_log l…

spring boot项目敏感配置信息如何加密?

一般情况下&#xff0c;spring boot项目为了能够实时刷新配置信息&#xff0c;都会把配置文件放在nacos之类的配置中心上。但是这样就会存在一个问题&#xff0c;一些比较敏感的配置信息&#xff0c;比如数据库密码&#xff0c;一旦被泄露&#xff0c;就会有严重的数据安全问题…

剩余电流式电气火灾监控系统在火力发电厂的应用

张心志 安科瑞电气股份有限公司 上海嘉定 201801 摘要&#xff1a;本文首先指出了在火力发电厂中应用电气火灾监控系统的重要性&#xff0c;接着研究分析了电气火灾监控系统的应用情况&#xff0c;主要从 系统简介、电气火灾原因等方面进行了分析。*后从配电箱、火灾监控设备…