SpringBoot整合FastDFS

什么是FastDFS

哈喽,大家好,我是花臂。

FastDFS相信大家都不陌生吧,它是一个轻量级的分布式文件系统,就是专门存储文件的,而且FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传,下载等服务,目前很多中小型公司用的比较广泛。

FastDFS服务端有两个角色:跟踪器(tracker) 和存储节点(storage)。跟踪器主要做调度工作,在访问上起负载均衡的作用。

上传交互过程

1、Storage Server向Tracker Server定时发送上传状态信息 ----> 2、Client向Tracker Server发送上传连接请求 ----> 3、Tracker Server查阅可用的Storage ----> 4、Tracker Server向Client返回信息(Storage的ip和端口) ----> 5、Client向Storage Server上传文件(file content和metadata) ----> 6、Storage Server生成file_id ----> 7、Storage Server将上传内容写入磁盘 ----> 8、Storage Server向Client返回file_id(路径信息和文件名) ----> 9、Client存储文件信息

下载交互过程

1、Storage Server向Tracker Server定时发送上传状态信息 ----> 2、Client向Tracker Server发送下载连接请求 ----> 3、Tracker Server查阅可用的Storage(检验同步状态) ----> 4、Tracker Server向Client返回信息(Storage的ip和端口) ----> 5、根据组名、路径、文件名Client向Storage Server下载文件 ----> 6、Storage Server查找文件 ----> 7、Storage Server向Clicent返回file_content

下载安装FastDFS

因为传统的linux下载安装FastDFS实在是太麻烦了,所以我们不用那个直接用docker安装,要是不会的,可以去学一下,很简单的。

docker run -d --restart=always --privileged=true --net=host --name=fastdfs -e IP=192.168.232.140 -e WEB_PORT=80 -v ${HOME}/fastdfs:/var/local/fdfs registry.cn-beijing.aliyuncs.com/tianzuo/fastdfs

//--restart=always:docker启动的时候自动启动容器
//--privileged=true:设置容器的权限为root
//--net=host:设置容器和宿主机共用网络
//--name 容器名称
//-e IP:本机IP地址
//-e WEB_PORT:设置端口号
//-v ${HOME}/fastdfs:/var/local/fdfs是指:将${HOME}/fastdfs这个目录挂载到容器里的/var/local/fdfs这个目录里。所以上传的文件将被持久化到${HOME}/fastdfs/storage/data里

具体代码实现

创建springboot工程导入依赖

!maven依赖

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

!yml文件

fdfs:
  so-timeout: 2500       # 读取时间
  connect-timeout: 600   # 连接超时时间
  thumb-image:           # 缩略图
    width: 100
    height: 100
  tracker-list:          # tracker服务配置地址列表
    - 116.62.44.5:22122
upload:
  base-url: http://116.62.44.5/    #上传成功后返回地址的前缀
  allow-types:                     #上传文件类型
    - image/jpeg
    - image/png
    - image/bmp
    - image/gif

!配置类UploadProperties

@ConfigurationProperties(prefix = "upload")
@Data
public class UploadProperties {

    //上传成功后返回地址的前缀
    private String baseUrl;
    //上传文件的类型
    private List<String> allowTypes;
}

!controller

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

    @Autowired
    private UploadService uploadService;

    @RequestMapping("/fileupload")
    public Map<String, Object> upload(MultipartFile mr) {
        System.out.println(mr.getOriginalFilename());
        Map<String, Object> map=new HashMap<>();
        String path = uploadService.uploadImage(mr);
        map.put("path",path);
        return map;
    }
}

!service

@Component
@EnableConfigurationProperties(UploadProperties.class)
public class UploadService {

    private Log log= LogFactory.getLog(UploadService.class);
    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private UploadProperties prop;

    public String uploadImage(MultipartFile file) {
        // 1、校验文件类型
        String contentType = file.getContentType();
        if (!prop.getAllowTypes().contains(contentType)) {
            throw new RuntimeException("文件类型不支持");
        }
        // 2、校验文件内容
        try {
            //ImageIO这个类是可以操作图片的,获取图片信息啥的
            BufferedImage image = ImageIO.read(file.getInputStream());
            if (image == null || image.getWidth() == 0 || image.getHeight() == 0) {
                throw new RuntimeException("上传文件有问题");
            }
        } catch (IOException e) {
            log.error("校验文件内容失败....{}", e);
            throw new RuntimeException("校验文件内容失败"+e.getMessage());
        }

        try {
            // 3、上传到FastDFS
            // 3.1、获取扩展名
            //StringUtils.substringAfterLast(uri,".")这个方法表示获取uri分隔符"."后面的内容
            String extension = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
            // 3.2、上传
            //最后一个参数表示额外的属性
            StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), extension, null);
            // 返回路径
            return prop.getBaseUrl() + storePath.getFullPath();
        } catch (IOException e) {
            log.error("【文件上传】上传文件失败!....{}", e);
            throw  new RuntimeException("【文件上传】上传文件失败!"+e.getMessage());
        }
    }

}

!index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>文件上传</h1>
<form method="post" action="/upload/fileupload" enctype="multipart/form-data">
    <input type="file" name="mr"><br>
<input type="submit" value="上传">
</form>

</body>
</html>

测试


ok,本次教程就到这儿,有什么疑问,欢迎下方评论区留言!

评论区



© [2020] · Powered by Typecho · Theme by Morecho
鄂ICP备20005123号