java调用fastdfs分布式文件系统

10 篇文章 0 订阅
2 篇文章 0 订阅

架构图

在这里插入图片描述

上传流程

在这里插入图片描述

  1. client询问tracker上传到的 storage,不需要附加参数;
  2. tracker返回一台可用的storage;
  3. client直接和storage 通讯完成文件上传

下载流程

在这里插入图片描述

  1. client询问tracker下载文件的storage,参数为文件标识(组名和文件名);
  2. tracker返回一台可用的storage;
  3. client直接和storage通讯完成文件下载。

安装教程

其他博客

测试上传:
http://192.168.166.140/group1/M00/00/00/wKimjGJCy2yAGoYkAAEZCxQ4CEc116.jpg
http://192.168.166.140/group1/M00/00/00/wKimjGJD6O6ATd6TAAF5_l7OiZ8751.jpg
http://192.168.166.140/group1/M00/00/00/wKimjGJD6PSAS59yAAHrcOF67mw325.jpg

卷名:group1
文件名:M00/00/00/wKimjGJCy2yAGoYkAAEZCxQ4CEc116.jpg
其中 M00 是一个虚拟目录,相当于 windows 中的快捷方式,引用的是$store_path0/data目录。

java调用

github连接
下载完后自己编译:mvn clean install
在这里插入图片描述
成功之后会有个jar包
在这里插入图片描述
maven仓库中也有这个jar包
在这里插入图片描述

jar包中常用依赖类

CLientGlobal

用于加载配置文件的公共客户端工具。
常用方法:

  • init(String conf_filename); 根据配置文件路径及命名,加载配置文件并设置客户端公共参数,配置文件类型为 conf 文件。可以使用绝对路径或相对路径加载。
  • initByProperties(Properties props); 根据 Properties 对象设置客户端公共参数。

注意:使用 conf 或 properties 进行客户端参数配置时,参数 key 命名不同。

TrackerClient

跟踪器客户端类型。创建此类型对象时,需传递跟踪器组,就是跟踪器的访问地址信息。无参构造方法默认使用ClientGlobal.g_tracker_group 常量作为跟踪器组来构造对象。
创建对象的方式为:
new TrackerClient(); 或 new TrackerClient(ClientGlobal.g_tracker_group)

TrackerServer

跟踪器服务类型。此类型的对象是通过跟踪器客户端对象构建的。实质上就是一个与FastDFS Tracker Server 的链接对象。是代码中与 Tracker Server 链接的工具。
构建对象的方式为:
trackerClient. getTrackerServer ();

StorageServer

存储服务类型。此类型的对象是通过跟踪器客户端对象构建的。实质上就是一个与FastDFS Storage Server 的链接对象。是代码中与 StroageServer 链接的工具。获取的具体存储服务链接,是由 Tracker Server 分配的,所以构建存储服务对象时,需要依赖跟踪器服务对象。
构建对象的方式为:
trackerClient.getStoreStorage(trackerServer);

StorageClient

存储客户端类型。此类型的对象是通过构造方法创建的。创建时,需传递跟踪服务对象和存储服务对象。此对象实质上就是一个访问 FastDFS Storage Server 的客户端对象,用于实现文件的读写操作。
创建对象的方式为:
new StorageClient(trackerServer, storageServer);

常用方法有:

upload_file(String local_filename, String file_ext_name,NameValuePair[] meta_list); 上传文件的方法,参数 local_filename为要上传的本地文件路径及文件名,可使用绝对路径或相对路径;参数file_ext_name为上传文件的扩展名,如果传递null,则自动解析文件扩展名;参数meta_list 是用于设置上传文件的源数据的,如上传用户、上传描述等。

download_file(String group_name, String remote_file_name); 下载文件的方法,参数group为组名/卷
名,就是 Storage Server中/etc/fdfs/storage.conf 配置文件中配置的group_name 参数值,也是要下载的文件所在组/卷的命名;参数 remote_file_name 为要下载的文件的路径及文件名。

delete_file(String group_name, String remote_file_name); 删除文件的方法,参数含义同
download_file方法参数。

pom.xml引入依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
   <dependencies>
        <!--SpringBoot Web启动-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--模板引擎 thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--lombok插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
            <scope>provided</scope>
        </dependency>
        <!--FastDFS依赖-->
        <dependency>
            <groupId>org.csource</groupId>
            <artifactId>fastdfs-client-java</artifactId>
            <version>1.29-SNAPSHOT</version>
        </dependency>
    </dependencies>

项目结构:
在这里插入图片描述

fdfs_client.conf

#连接超时
connect_timeout = 2
#网络超时
network_timeout = 30
#编码格式
charset = UTF-8
#tracker端口号
http.tracker_http_port = 8080
#防盗链功能
http.anti_steal_token = no
#秘钥
http.secret_key = FastDFS1234567890
#tracker ip:端口号
tracker_server = 192.168.166.140:22122
#连接池配置
connection_pool.enabled = true
connection_pool.max_count_per_entry = 500
connection_pool.max_idle_time = 3600
connection_pool.max_wait_time_in_ms = 1000

UploadController

package com.shengun.controller;

import com.shengun.pojo.FastDFSFile;
import com.shengun.utill.FastDFSClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.InputStream;

@Controller
@Slf4j
public class UploadController {


    @Value("${fastdfs.ip}")
    private String fastdfsUrl;

    /**
     * 页面跳转
     *
     * @return
     */
    @GetMapping("/")
    public String index() {
        return "upload";
    }

    /**
     * 上传文件
     * @param file
     * @param redirectAttributes
     * @return
     */
    @PostMapping("/upload")
    public String singleFileUpload(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) {
        if (file.isEmpty()) {
            redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
            return "redirect:uploadStatus";
        }
        try {
            // 上传文件拿到返回的文件路径
            String path=saveFile(file);
            redirectAttributes.addFlashAttribute("message", "You successfully uploaded '" + file.getOriginalFilename() + "'");
            redirectAttributes.addFlashAttribute("path", "file path url '" + path + "'");
        } catch (Exception e) {
            log.error("upload file failed",e);
        }
        return "redirect:/uploadStatus";
    }

    /**
     * 上传文件
     * @param multipartFile
     * @return
     * @throws Exception
     */
    public String saveFile(MultipartFile multipartFile) throws Exception{
        String[] fileAbsolutePath={};
        String fileName=multipartFile.getOriginalFilename();
        log.info("fileName:" + fileName);
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
        log.info("ext:" + ext);
        byte[] file_buff = null;
        InputStream inputStream=multipartFile.getInputStream();

        if(inputStream!=null){
            int len1 = inputStream.available();
            file_buff = new byte[len1];
            inputStream.read(file_buff);
        }
        log.info("file_buff:" + file_buff.toString());
        inputStream.close();
        FastDFSFile file = new FastDFSFile(fileName, file_buff, ext);
        //上传文件
        try {
            fileAbsolutePath = FastDFSClient.upload(file);
        } catch (Exception e) {
            log.error("upload file Exception!",e);
        }

        if (fileAbsolutePath==null) {
            log.error("upload file failed,please upload again!");
        }

        log.info(fastdfsUrl);
        String path=FastDFSClient.getTrackerUrl() +fileAbsolutePath[0]+ "/"+fileAbsolutePath[1];
        log.info("path:"+ path);
//        String path=fastdfsUrl + "/" +fileAbsolutePath[0]+ "/"+fileAbsolutePath[1];
        return path;
    }


        /**
         * 页面跳转
         * @return
         */
    @GetMapping("/uploadStatus")
    public String uploadStatus() {
        return "uploadStatus";
    }

}

utill FastDFSClient

package com.shengun.utill;

import com.shengun.pojo.FastDFSFile;
import lombok.extern.slf4j.Slf4j;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;


@Slf4j
public class FastDFSClient {

    static{
        try {
            String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            log.error("FastDFS Client Init Fail!",e);
        }
    }

    /**
     * @param file
     * @return
     */
    public static String[] upload(FastDFSFile file) {
        log.info("File Name: " + file.getName() + "  ,File Length:" + file.getContent().length);

        //文件属性信息
        NameValuePair[] meta_list = new NameValuePair[1];
        meta_list[0] = new NameValuePair("author", file.getAuthor());

        long startTime = System.currentTimeMillis();
        String[] uploadResults = null;
        StorageClient storageClient=null;

        try {
            //获取storage客户端
            storageClient = getStorageClient();
            //上传
            uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
        } catch (Exception e) {
            log.error("when uploadind the file:"+file.getName(),e.getMessage());
        }

        log.info("upload_file time used:" + (System.currentTimeMillis() - startTime) + "ms");
        //验证上传结果
        if (uploadResults == null && storageClient!=null) {
            log.error("upload file fail, error code:" + storageClient.getErrorCode());
        }
        //上传文件成功会返回 groupName。
        log.info("upload file successfully!!!" + "group_name:" + uploadResults[0] + ",remoteFileName:" + " " + uploadResults[1]);
        return uploadResults;
    }

    /**
     * 获取文件信息
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static FileInfo getFile(String groupName, String remoteFileName) {
        try {
            StorageClient storageClient = getStorageClient();
            return storageClient.get_file_info(groupName, remoteFileName);
        } catch (IOException e) {
            log.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            log.error("Non IO 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 = getStorageClient();
            byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
            InputStream ins = new ByteArrayInputStream(fileByte);
            return ins;
        } catch (IOException e) {
            log.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            log.error("Non IO Exception: Get File from Fast DFS failed", e);
        }
        return null;
    }


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

    /**
     * 删除文件
     * @param groupName
     * @param remoteFileName
     * @throws Exception
     */
    public static void deleteFile(String groupName, String remoteFileName)
            throws Exception {
        StorageClient storageClient = getStorageClient();
        int i = storageClient.delete_file(groupName, remoteFileName);
        log.info("delete file successfully!!!" + i);
    }

    /**
     * 生成Tracker服务器端
     * @return
     * @throws IOException
     */
    private static TrackerServer getTrackerServer() throws IOException {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getTrackerServer();
        return trackerServer;
    }

    /**
     * 获取文件路径
     * @return
     * @throws IOException
     */
    public static String getTrackerUrl() throws Exception {
        TrackerClient trackerClient = new TrackerClient();
        TrackerServer trackerServer = trackerClient.getTrackerServer();
        StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer);
        return "http://"+storeStorage.getInetSocketAddress().getHostString()+":80/";
    }


}

pojo FastDFSFile

package com.shengun.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class FastDFSFile {
    private String name;
    private byte[] content;
    private String ext;
    private String md5;
    private String author;
    private String height;

    public FastDFSFile(String name, byte[] content, String ext) {
        this.name = name;
        this.content = content;
        this.ext = ext;
    }
}

模板template upload.html uploadStatus.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Spring Boot file upload example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
    <input type="file" name="file" /><br/><br/>
    <input type="submit" value="Submit" />
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Spring Boot - Upload Status</h1>
<div th:if="${message}">
    <h2 th:text="${message}"/>
</div>
<div th:if="${path}">
    <h2 th:text="${path}"/>
</div>

</body>
</html>

测试

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值