分布式文件存储_FastDFS 入门知识点(含代码)

一、FastDFS简介

1、什么是FastDFS

  FastDFS是一个开源的轻量级分布式文件系统,主要功能包括文件储存、文件同步、文件上传下载等,解决了大容量储存和负载均衡的问题,特别适合视频和在线相册等网站。

2、FastDFS特点

  FastDFS充分的考虑了冗余备份、负载均衡、线性扩容的机制,是一个高可用、高性能的文件系统。

3、FastDFS构成

  FastDFS 架构包括 Tracker和 Storage,客户端请求 Tracker进行文件上传、下载,通过Tracker调度最终由 Storage完成文件上传和下
载。
  Tracker作用是负载均衡和调度,通过 Tracker 在文件上传时可以根据一些策略找到Storage提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。
  Storage 作用是文件存储,客户端上传的文件最终存储在Storage 服务器上,Storage 没有实现自己的文件系统而是利用操作系统的文件系统来管理文件。可以将storage称为存储服务器。

二、文件上传流程

分布式文件存储_FastDFS 入门知识点(含代码)_第1张图片
分布式文件存储_FastDFS 入门知识点(含代码)_第2张图片

三、FastDFS搭建

1、环境准备

利用docker搭建FastDFSD 开发环境

//1、拉取镜像
docker pull morunchang/fastdfs

//2、运行tracker
docker run ‐d ‐‐name tracker ‐‐net=host morunchang/fastdfs sh tracker.sh

//3、运行storage
docker run ‐d ‐‐name storage ‐‐net=host ‐e TRACKER_IP=<your tracker
server address>:22122 ‐e GROUP_NAME=<group name> morunchang/fastdfs sh
storage.sh

注意:使用的网络模式是–net=host, 替换为你机器的Ip即可
是组名,即storage的组
如果想要增加新的storage服务器,再次运行该命令,注意更换 新组名

//4、修改nginx的配置,进入storage的容器内部,修改nginx.conf
docker exec ‐it storage /bin/bash
//进入后
vi /data/nginx/conf/nginx.conf
//添加以下内容
location /group1/M00 {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache http‐cache;
proxy_cache_valid 200 304 12h;
proxy_cache_key $uri$is_args$args;
proxy_pass http://fdfs_group1;
expires 30d;
}

//5、退出容器
exit

//6、重启storage容器
docker restart storage


2、工程搭建

(1)修改pom.xml,引入依赖

<dependencies>
	<dependency>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring‐boot‐starter‐webartifactId>
	dependency>
	
	<dependency>
		<groupId>net.oschina.zcx7878groupId>
		<artifactId>fastdfs‐client‐javaartifactId>
		<version>1.27.0.0version>
	dependency>
	
	<dependency>
		<groupId>com.changgougroupId>
		<artifactId>changgou_commonartifactId>
		<version>1.0‐SNAPSHOTversion>
	dependency>
dependencies>

(2)在resources文件夹下创建fasfDFS的配置文件fdfs_client.conf

connect_timeout = 60     //连接超时时间,单位为秒。
network_timeout = 60     //通信超时时间,单位为秒。发
charset = UTF‐8          //字符集
http.tracker_http_port = 8080    //tracker的http端口
tracker_server = 192.168.200.128:22122    //tracker服务器IP和端口设置

(3)在resources文件夹下创建application.yml

spring:
	servlet:
		multipart:
			max‐file‐size: 10MB   #单个文件大小
			max‐request‐size: 10MB #置总上传的数据大小

(4)创建com.changgou.file包,创建启动类FileApplication

@SpringBootApplication
@EnableEurekaClient
public class FileApplication {
	public static void main(String[] args) {
		SpringApplication.run(FileApplication.class);
	}
}

3、文件信息封装

创建com.changgou.file.pojo.FastDFSFile

public class FastDFSFile {
	//文件名字
    private String name;
    //文件内容
    private byte[] content;
    //文件扩展名
    private String ext;
    //文件MD5摘要值
    private String md5;
    //文件创建作者
    private String author;

    public FileTest(String name, byte[] content, String ext, String
            height, String width, String author) {
        super();
        this.name = name;
        this.content = content;
        this.ext = ext;
        this.author = author;
    }

    public FileTest(String name, byte[] content, String ext) {
        super();
        this.name = name;
        this.content = content;
        this.ext = ext;
    }
		// getter and setter ...
}

4、文件操作

  创建FastDFSClient类,放在com.changgou.file.util下在该类中实现FastDFS信息获取以及文件的相关操作

public class FastDFSClient {

	private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);

    /***
     * 初始化加载FastDFS的TrackerServer配置
     */
    static {
        try {
            String filePath = new
                    ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            logger.error("FastDFS Client Init Fail!", e);
        }
    }

    /***
     * 文件上传
     * @param file
     * @return
     */
    public static String[] upload(FastDFSFile file) {
        //获取文件的作者
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] = new NameValuePair("author", file.getAuthor());
        //接收返回数据
        String[] uploadResults = null;
        StorageClient storageClient = null;
        try {
            //创建StorageClient客户端对象
            storageClient = getTrackerClient();
            /***
             * 文件上传
             * 1)文件字节数组
             * 2)文件扩展名
             * 3)文件作者
             */
            uploadResults = storageClient.upload_file(file.getContent(),
                    file.getExt(), meta_list);
        } catch (Exception e) {
            logger.error("Exception when uploadind the file:" +
                    file.getName(), e);
        }
        if (uploadResults == null && storageClient != null) {
            logger.error("upload file fail, error code:" +
                    storageClient.getErrorCode());
        }
        //获取组名
        String groupName = uploadResults[0];
        //获取文件存储路径
        String remoteFileName = uploadResults[1];
        return uploadResults;
    }

    /***
     * 获取文件信息
     * @param groupName:组名
     * @param remoteFileName:文件存储完整名
     * @return
     */
    public static FileInfo getFile(String groupName, String remoteFileName) {
        try {
            StorageClient storageClient = getTrackerClient();
            return storageClient.get_file_info(groupName,
                    remoteFileName);
        } catch (Exception e) {
            logger.error("Exception: Get File from Fast DFS failed", e);
        }
        return null;
    }

    /***
     * 文件下载
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static InputStream downFile(String groupName, String remoteFileName) {
        try {
            //创建StorageClient
            StorageClient storageClient = getTrackerClient();
            //下载文件
            byte[] fileByte = storageClient.download_file(groupName,
                    remoteFileName);
            InputStream ins = new ByteArrayInputStream(fileByte);
            return ins;
        } catch (Exception e) {
            logger.error("Exception: Get File from Fast DFS failed", e);
        }
        return null;
    }

    /***
     * 文件删除
     * @param groupName
     * @param remoteFileName
     * @throws Exception
     */
    public static void deleteFile(String groupName, String remoteFileName) throws Exception {
        //创建StorageClient
        StorageClient storageClient = getTrackerClient();
        //删除文件
        int i = storageClient.delete_file(groupName, remoteFileName);
    }

    /***
     * 获取Storage组
     * @param groupName
     * @return
     * @throws IOException
     */
    public static StorageServer[] getStoreStorages(String groupName) throws IOException {
        //创建TrackerClient
        TrackerClient trackerClient = new TrackerClient();
        //获取TrackerServer
        TrackerServer trackerServer = trackerClient.getConnection();
        //获取Storage组
        return trackerClient.getStoreStorages(trackerServer, groupName);
    }

    /***
     * 获取Storage信息,IP和端口
     * @param groupName
     * @param remoteFileName
     * @return
     * @throws IOException
     */
    public static ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
    }

    /***
     * 获取Tracker服务地址
     * @return
     * @throws IOException
     */
    public static String getTrackerUrl() throws IOException {
        return "http://" + getTrackerServer().getInetSocketAddress().getHostString() + ":" + ClientGlobal.getG_tracker_http_port() + "/";
    }

    /***
     * 获取Storage客户端
     * @return
     * @throws IOException
     */
    private static StorageClient getTrackerClient() throws IOException {
        TrackerServer trackerServer = getTrackerServer();
        StorageClient storageClient = new StorageClient(trackerServer, null);
        return storageClient;
    }

    /***
     * 获取Tracker
     * @return
     * @throws IOException
     */
    private static TrackerServer getTrackerServer() throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerServer;
    }
}

5、文件上传

创建一个FileController,在该控制器中实现文件上传操作,代码如下:


@RestController
@RequestMapping("/file")
public class FileController {
    
    @PostMapping("/upload")
    public Result uploadFile(MultipartFile file) {
        try {
            //判断文件是否存在
            if (file == null) {
                throw new RuntimeException("文件不存在");
            }
            //获取文件的完整名称
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isEmpty(originalFilename)) {
                throw new RuntimeException("文件不存在");
            }
            //获取文件的扩展名称 abc.jpg jpg
            String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            //获取文件内容
            byte[] content = file.getBytes();
            //创建文件上传的封装实体类
            FastDFSFile fastDFSFile = new FastDFSFile(originalFilename, content, extName);
            //基于工具类进行文件上传,并接受返回参数 String[]
            String[] uploadResult = FastDFSClient.upload(fastDFSFile);
            //封装返回结果
            String url = FastDFSClient.getTrackerUrl() + uploadResult[0] + "/" + uploadResult[1];
            return new Result(true, StatusCode.OK, "文件上传成功", url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result(false, StatusCode.ERROR, "文件上传失败");
    }
}

6、Postman测试文件上传

步骤:
1、选择post请求方式,输入请求地址 http://localhost:9008/upload
2、填写Headers

Key:Content‐Type
Value:multipart/form‐data

3、填写body
选择form-data 然后选择文件file 点击添加文件,最后发送即可。

你可能感兴趣的:(框架阶段笔记,java,docker,分布式,fastdfs)