【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储

文章目录

  • 1.简介
  • 2.添加配置
    • 2.1.在maven的pom.xml中添加fastDfs依赖包
    • 2.2.修改应用配置文件
  • 3.添加工具类
  • 4.测试接口编写
  • 5.测试
    • 5.1.上传图片
    • 5.2.下载图片
    • 5.3.删除图片
  • 6.项目配套代码

1.简介

如果应用是在集群部署,如果文件存储需要共享要通过linux的nfs服务来实现共享,或者把文件存储在分布式文件存储系统里面,例如FastDFS,minio,本章讲解集成FastDFS实现分布式文件存储。
FastDFS环境搭建请参考https://dominick-li.blog.csdn.net/article/details/121529247

2.添加配置

2.1.在maven的pom.xml中添加fastDfs依赖包

        
        
            com.github.tobato
            fastdfs-client
            1.27.2
        

2.2.修改应用配置文件

编辑application.yml文件

spring:
  application:
    name: fastdfs
  servlet:
    multipart:
      enabled: true
      max-file-size: 10MB
      max-request-size: 20MB
fdfs:
  # 连接超时   默认值(60)
  connect-timeout: 6000
  # 读取时间   默认值(60)
  so-timeout: 6000
  # 生成缩略图参数
  thumb-image:
    enabled: true
    width: 250
    height: 150
  #Tracte服务的ip和端口,多个可以用逗号隔开,或者通过nginx做一个负载均衡然后配置一个即可。  
  tracker-list: 192.168.94.128:22122

server:
  port: 8024

3.添加工具类

下面定义了上传文件,下载文件,删除文件的方法.

package com.ljm.boot.fastdfs.config;

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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;

/**
 * @author Dominick Li
 * @CreateTime 2020/3/29 17:56
 * @description 操作dfs 工具类
 **/
@Component
public class FileDfsUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileDfsUtil.class);

    @Resource
    private FastFileStorageClient storageClient;

    @Value("${fdfs.thumb-image.enabled}")
    private boolean thumbEnabled;

    /**
     * 上传文件
     */
    public String upload(MultipartFile multipartFile) throws Exception {
        String originalFilename = multipartFile.getOriginalFilename().
                substring(multipartFile.getOriginalFilename().
                        lastIndexOf(".") + 1);
        StorePath storePath = null;
        if (thumbEnabled) {
            //上传文件并生成缩略图,如果返回的图片名称 test.jpg,则缩略图的名称是test_宽x高.jpg,例如test_250x150.jpg
            storePath = this.storageClient.uploadImageAndCrtThumbImage(multipartFile.getInputStream(), multipartFile.getSize(), originalFilename, null);
        } else {
            //上传文件
            storePath = this.storageClient.uploadFile(multipartFile.getInputStream(), multipartFile.getSize(), originalFilename, null);
        }
        return storePath.getFullPath();
    }


    /**
     * 删除文件
     */
    public void deleteFile(String fileUrl, boolean hasThumbnail) {
        try {
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
            if (hasThumbnail) {
                //删除缩略图
                String[] arr = fileUrl.split("\\.");
                String thumbnailFileUrl = arr[0] +"_"+ width + "x" + height + "." + arr[1];
                storePath = StorePath.parseFromUrl(thumbnailFileUrl);
                storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
            }
        } catch (Exception e) {
            LOGGER.info(e.getMessage());
        }
    }

    /**
     * 下载文件
     */
    public byte[] downloadFile(String fileUrl) {
        StorePath storePath = StorePath.parseFromUrl(fileUrl);
        return storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
    }
}

4.测试接口编写

package com.ljm.boot.fastdfs.controller;

import com.ljm.boot.fastdfs.config.FileDfsUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author Dominick Li
 * @CreateTime 2020/3/29 17:56
 * @description 测试上传下载和删除
 **/
@RestController
@RequestMapping("/file")
public class FileController {

    @Resource
    private FileDfsUtil fileDfsUtil;

    /**
     * 测试FastDFS文件上传
     * 如果要生成缩略图,则缩略图的名字为图片后缀加_图片宽*高
     * 使用接口返回的名称和nginx的访问地址拼接即可在浏览器访问 http://192.168.94.128:9999/group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg
     * 如果正常图片是group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg 则缩略图为  group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436_250x150.jpg
     */
    @PostMapping(value = "/")
    public ResponseEntity<String> uploadFile(MultipartFile file) {
        String result;
        try {
            String path = fileDfsUtil.upload(file);
            if (!StringUtils.isEmpty(path)) {
                result = path;
            } else {
                result = "上传失败";
            }
        } catch (Exception e) {
            e.printStackTrace();
            result = "服务异常";
        }
        return ResponseEntity.ok(result);
    }

    /**
     * 文件删除
     * http://localhost:8024/file/fileUrl=group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg&hasThumbnail=true
     * @param fileUrl 上传接口返回的文件名
     * @param hasThumbnail 是否有缩略图
     */
    @DeleteMapping(value = "/")
    public ResponseEntity<String> deleteByPath(String fileUrl,@RequestParam(value = "hasThumbnail",required = false,defaultValue = "false") boolean hasThumbnail) {
        fileDfsUtil.deleteFile(fileUrl,hasThumbnail);
        return ResponseEntity.ok("SUCCESS");
    }

    /**
     * 文件下载
     * http://localhost:8024/download?fileUrl=group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg
     * @param fileUrl 上传接口返回的文件名
     */
    @GetMapping("/")
    public void downLoad(@RequestParam String fileUrl, HttpServletResponse response) throws IOException {
        // 获取文件
        byte[] bytes = fileDfsUtil.downloadFile(fileUrl);
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        response.reset();
        response.setContentType("application/x-download");
        response.addHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
        response.getOutputStream().write(bytes);
        response.getOutputStream().close();

    }
}

5.测试

5.1.上传图片

通过postman调用localhost:8024/file/接口进行文件上传
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第1张图片
把nginx的访问地址和文件名拼接即可访问图片
访问原图: http://192.168.94.128:9999/group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg
访问缩略图: http://192.168.94.128:9999/group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436_250x150.jpg
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第2张图片
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第3张图片

5.2.下载图片

浏览器访问: http://localhost:8024/file/?fileUrl=group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg
可以看到浏览器左下角有一张图片下载成功.
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第4张图片

5.3.删除图片

通过postman请求接口,请求类型选择DELETE
http://localhost:8024/file/fileUrl=group1/M00/00/00/wKhegGGeylOAJx8yAB7ib2v_DBQ436.jpg
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第5张图片
删除成功再次通过浏览器访问图片会发现图片已经找不到了,但是缩略图没有删掉。
【SpringBoot框架篇】24.集成FastDFS实现文件的分布式存储_第6张图片

6.项目配套代码

gitee代码地址

创作不易,要是觉得我写的对你有点帮助的话,麻烦在gitee上帮我点下 Star

【SpringBoot框架篇】其它文章如下,后续会继续更新。

  • 1.搭建第一个springboot项目
  • 2.Thymeleaf模板引擎实战
  • 3.优化代码,让代码更简洁高效
  • 4.集成jta-atomikos实现分布式事务
  • 5.分布式锁的实现方式
  • 6.docker部署,并挂载配置文件到宿主机上面
  • 7.项目发布到生产环境
  • 8.搭建自己的spring-boot-starter
  • 9.dubbo入门实战
  • 10.API接口限流实战
  • 11.Spring Data Jpa实战
  • 12.使用druid的monitor工具查看sql执行性能
  • 13.使用springboot admin对springboot应用进行监控
  • 14.mybatis-plus实战
  • 15.使用shiro对web应用进行权限认证
  • 16.security整合jwt实现对前后端分离的项目进行权限认证
  • 17.使用swagger2生成RESTful风格的接口文档
  • 18.使用Netty加websocket实现在线聊天功能
  • 19.使用spring-session加redis来实现session共享
  • 20.自定义@Configuration配置类启用开关
  • 21.对springboot框架编译后的jar文件瘦身
  • 22.集成RocketMQ实现消息发布和订阅
  • 23.集成smart-doc插件零侵入自动生成RESTful格式API文档
  • 24.集成FastDFS实现文件的分布式存储
  • 25.集成Minio实现文件的私有化对象存储
  • 26.集成spring-boot-starter-validation对接口参数校验
  • 27.集成mail实现邮件推送带网页样式的消息
  • 28.使用JdbcTemplate操作数据库
  • 29.Jpa+vue实现单模型的低代码平台
  • 30.使用sharding-jdbc实现读写分离和分库分表
  • 31.基于分布式锁或xxx-job实现分布式任务调度
  • 32.基于注解+redis实现表单防重复提交
  • 33.优雅集成i18n实现国际化信息返回
  • 34.使用Spring Retry完成任务的重试

你可能感兴趣的:(springBoot,java,spring,boot,restful)