当前位置:   article > 正文

FastDfs的介绍和使用_fastdfs客戶端怎么使用

fastdfs客戶端怎么使用

FastDfs的介绍和使用

一. 基本概念

Fastdfs是用C语言编写的一款开源的分布式文件系统。Fastdfs为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 Fastdfs很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

Fastdfs架构包括Tracker serverStorage server。客户端请求Tracker server 进行文件上传、下载,通过 Tracker server 调度,最终由Storage server完成文件上传和下载。

Tracker server作用是负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。

二. Fastdfs系统结构

Storage作用是文件存储,客户端上传的文件最终存储在Storage服务器上。

服务端两个角色:

  • Tracker:作用是负载均衡和调度

  • Storage:作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上

  • 客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。如:/group1/M00/01/B2/CgAIC2Md0nWAKjOCAAQRef-xdIY168.jpg

  • 组名/卷:文件上传后所在的Storage组名称,在文件上传成功后有Storage服务器返回,需要客户端自行保存

  • 虚拟磁盘路径:Storage配置的虚拟路径,与磁盘选项 store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推

  • 数据两级目录:Storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件

  • 文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息

0. storage会定期向tracker上传当前状态【心跳机制】
1. 客户端发送请求,请求tracker【调度中心】
2. tracker选择哪一个storage能使用,并且返回能用的storage
3. 客户端把上传的附件,上传到storage中去
4. storage会向客户端返回上传文件的路径
  • 1
  • 2
  • 3
  • 4
  • 5
  • 可以使用docker搭建fastdfs文件服务器

三. 使用FastDfs系统

  1. 导入依赖

    <!--fastdfs-->
    <dependency>
        <groupId>cn.bestwu</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27</version>
    </dependency>
    
    <!--用来获取文件扩展名的包-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.8.0</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  2. 添加配置文件fdfs_client.conf 到资源文件夹

    tracker_server=123.207.27.208:22122  
    #22122是tracker的端口 - 上传
    #访问直接使用域名:123.207.27.208
    
    • 1
    • 2
    • 3
  3. 测试代码

    // 1、加载配置文件,配置文件中的内容就是 tracker 服务的地址。
    ClientGlobal.init("D:/maven_work/fastDFS-demo/src/fdfs_client.conf");
    // 2、创建一个 TrackerClient 对象。直接 new 一个。
    TrackerClient trackerClient = new TrackerClient();
    // 3、使用 TrackerClient 对象创建连接,获得一个 TrackerServer 对象。
    TrackerServer trackerServer = trackerClient.getConnection();
    // 4、创建一个 StorageServer 的引用,值为 null
    StorageServer storageServer = null;
    // 5、创建一个 StorageClient 对象,需要两个参数 TrackerServer 对象、StorageServer 的引用
    StorageClient storageClient = new StorageClient(trackerServer, storageServer);
    // 6、使用 StorageClient 对象上传图片。
    //扩展名不带“.”
    String[] strings = storageClient.upload_file("D:/pic/benchi.jpg", "jpg",null);
    // 7、返回数组。包含组名和图片的路径。
    /*
    组名:group1
    路径: M00/01/B3/CgAIC2Md3KGAGa0xAAALg4Ak6_M929.jpg
    */
    for (String string : strings) {
        System.out.println(string);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  4. 访问上传图片

    http://123.207.27.208/group1/M00/01/B3/CgAIC2Md3KGAGa0xAAALg4Ak6_M929.jpg
    
    • 1

四. FastDfsUtils工具类

package io.coderyeah.basic.util;

import org.csource.fastdfs.*;

/**
 * fastDfs工具类
 */
public class FastDfsUtils {

    //从classpath:resources中的内容最终会编译到classpath下
    public static String CONF_FILENAME = FastDfsUtils.class.getClassLoader().getResource("fdfs_client.conf").getFile();


    /**
     * 上传文件
     *
     * @param file
     * @param extName
     * @return
     */
    public static String upload(byte[] file, String extName) {

        try {
            ClientGlobal.init(CONF_FILENAME);

            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getConnection();
            StorageServer storageServer = null;

            StorageClient storageClient = new StorageClient(trackerServer, storageServer);

            String fileIds[] = storageClient.upload_file(file, extName, null);

            System.out.println(fileIds.length);
            System.out.println("组名:" + fileIds[0]);
            System.out.println("路径: " + fileIds[1]);
            //  /group1/M00/00/09/rBEACmKXF8-AUc6KAANsldwx3H4713.jpg
            return "/" + fileIds[0] + "/" + fileIds[1];
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 上传文件
     *
     * @param extName
     * @return
     */
    public static String upload(String path, String extName) {

        try {
            ClientGlobal.init(CONF_FILENAME);

            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getConnection();
            StorageServer storageServer = null;
            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            String fileIds[] = storageClient.upload_file(path, extName, null);

            System.out.println(fileIds.length);
            System.out.println("组名:" + fileIds[0]);
            System.out.println("路径: " + fileIds[1]);
            return "/" + fileIds[0] + "/" + fileIds[1];

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 下载文件
     *
     * @param groupName
     * @param fileName
     * @return
     */
    public static byte[] download(String groupName, String fileName) {
        try {

            ClientGlobal.init(CONF_FILENAME);

            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getConnection();
            StorageServer storageServer = null;

            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            byte[] b = storageClient.download_file(groupName, fileName);
            return b;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 删除文件
     *
     * @param groupName
     * @param fileName
     */
    public static void delete(String groupName, String fileName) {
        try {
            ClientGlobal.init(CONF_FILENAME);

            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getConnection();
            StorageServer storageServer = null;

            StorageClient storageClient = new StorageClient(trackerServer, storageServer);
            int i = storageClient.delete_file(groupName, fileName);
            System.out.println(i == 0 ? "删除成功" : "删除失败:" + i);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("删除异常," + e.getMessage());
        }
    }

//    public static void main(String[] args) {
//        FastDfsUtils.delete("group1","M00/00/0F/oYYBAGJ6IGaAWQeOAAbMJw3URKE510.gif");
//    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125

五. 文件上传接口

package io.coderyeah.basic.controller;

import io.coderyeah.basic.Result;
import io.coderyeah.basic.util.FastDfsUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Api(value = "文件的上传和下载接口", tags = "fastDfs文件上传")
@RestController
@RequestMapping("/fastDfs")
public class FastDfsController {
    /**
     * // @RequestPart 对复杂表单项的处理,默认name="file",与上传文件的name属性值一致
     */
    @ApiOperation("通过fastDfs文件上传到服务器")
    @PostMapping()
    public Result upload(@RequestPart(value = "file", required = true) MultipartFile file) {
        // 1.截取文件后缀名 如png jpg
        final String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        try {
            // 2.将图片上传服务器将文件名返回前端
            // /group1/M00/01/B2/CgAIC2Md0nWAKjOCAAQRef-xdIY168.jpg
            final String filepath = FastDfsUtils.upload(file.getBytes(), suffix);
            return Result.success(filepath,null); // 返回服务器文件路径
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail("上传失败!" + e.getMessage());
        }
    }

    @ApiOperation("删除文件")
    @DeleteMapping()
    public Result delete(@RequestParam("path") String path) {
        try {
            // 1.截取组名  /group1/M00/01/B2/CgAIC2Md0nWAKjOCAAQRef-xdIY168.jpg
            // 1.1临时路径
            final String tempPath = path.substring(1); // group1/M00/01/B2/CgAIC2Md0nWAKjOCAAQRef-xdIY168.jpg
            final String groupName = tempPath.substring(0, tempPath.indexOf("/")); // group1
            System.out.println(tempPath);
            System.out.println(groupName);
            // 2.远程路径
            final String remotePath = tempPath.substring(tempPath.indexOf("/") + 1);
            FastDfsUtils.delete(groupName, remotePath);
            return Result.success(null);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("删除失败" + e.getMessage());
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

六. 上传流程

前端:
    1.准备el-upload上传组件
    2.当我们点击上传按钮的时候,其实是在触发el-upload的action
    3.action调用后端接口:http://localhost:8080/fastDfs
    4.后端上传成功之后,返回到el-upload的:on-success="handleSuccess"
    5.在handleSuccess中,将后端返回的resultObj绑定给模型层的logo
后端:
    1.接收请求@RequestPart MultipartFile file
    2.调用FastDfsUtils完成文件上传得到返回值path
    3.然后将path设置给封装结果类的data传回给前端
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

七. 文件上传表单项

<el-form-item prop="logo" label="店铺Logo">
  <!--
  :on-preview="handlePreview" - 点击图片名时触发此函数 - 可以在这里做放大功能,这里不做
  :on-remove="handleRemove" - 点击删除时触发
  :on-success="handleSuccess" - 上传成功之后触发
  :file-list="fileList" - 文件列表
  action="http://localhost:8080/fastDfs/" - 文件上传接口地址
  -->
  <el-upload class="upload-demo"
             action="http://localhost:8080/fastDfs/"
             :on-preview="handlePreview"
             :on-remove="handleRemove"
             :on-success="handleSuccess"
             :file-list="fileList"
             list-type="picture">
    <el-button size="small" type="primary">点击上传</el-button>
    <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
  </el-upload>
</el-form-item>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

方法:

//文件上传的业务逻辑
handleSuccess(response, file, fileList) {
  this.shop.logo = response.data;
  console.log(response.data)
},

//文件删除的业务逻辑
handleRemove(file, fileList) {
  var filePath = file.response.data;
  this.$http.delete("/fastDfs?path=" + filePath)
      .then(res => {
        if (res.data.success) {
          this.$message({
            message: '删除成功!',
            type: 'success'
          });
        } else {
          this.$message({
            message: '删除失败!',
            type: 'error'
          });
        }
      })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/891111
推荐阅读
相关标签
  

闽ICP备14008679号