分布式文件系统详解(安装、Java整合)—FastDFS

✌全网粉丝20W+,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌

🍅文末获取项目下载方式🍅
链接点击直达:下载链接


一、概述

FastDFS是一个开源的高性能分布式文件系统。其主要 功能包括:文件存储、文件同步和文件访问(文件上传) 和文件下载),并且可以解决高容量和负载平衡 问题。FastDFS应满足其服务基础网站的要求 在照片共享站点和视频共享站点等文件上。

FastDFS有两个角色:跟踪器和存储。跟踪器负责 文件访问的计划和负载平衡。存储存储文件及其 功能是文件管理,包括:文件存储,文件同步,提供文件 访问接口。它还管理元数据,这些数据是代表属性的属性 作为文件的键值对。例如:width=1024,键为“width”和 值为“1024”。

跟踪器和存储包含一个或多个服务器。跟踪器中的服务器 或者可以随时将存储集群添加到集群或从集群中删除,而无需 影响在线服务。跟踪器集群中的服务器是对等的。

按文件卷/组组织以获得高容量的 storarge 服务器。 存储系统包含一个或多个卷,其文件独立于 这些卷。整个存储系统的容量等于所有存储系统的总和 卷的容量。文件卷包含一个或多个存储服务器,其文件 在这些服务器之间是相同的。文件卷中的服务器相互备份, 所有这些服务器都是负载平衡的。将存储服务器添加到 卷,此卷中已存在的文件将复制到此新服务器 自动,复制完成后,系统将切换此服务器 在线提供存储服务。

当整个存储容量不足时,可以添加一个或多个 卷以扩展存储容量。为此,您需要添加一个或 更多存储服务器。

文件的标识由两部分组成:卷名和 文件名。

1、FastDFS整体架构

FastDFS文件系统由两大部分构成,一个是客户端,一个是服务端

客户端通常指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端,FastDFS提供专有API访问,目前提供了C、Java和PHP几种编程语言的API,用来访问FastDFS文件系统。

服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)

tracker跟踪器主要做调度工作,起到均衡的作用;负责管理所有的 storage server和 group,每个 storage 在启动后会连接 tracker,告知自己所属 group 等信息,并保持周期性心跳。tracker记录group以及每个group的存储信息。在内存中记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽。因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。

storage存储节点主要提供存储文件和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份。存储文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别对应在/data/disk1-/data/disk10,则可将这10个目录都配置为storage的数据存储目录

按文件卷/组组织以获得高容量的 storarge 服务器。 存储系统包含一个或多个卷,其文件独立于 这些卷。整个存储系统的容量等于所有存储系统的总和 卷的容量。文件卷包含一个或多个存储服务器,其文件 在这些服务器之间是相同的。文件卷中的服务器相互备份, 所有这些服务器都是负载平衡的。将存储服务器添加到 卷,此卷中已存在的文件将复制到此新服务器 自动,复制完成后,系统将切换此服务器 在线提供存储服务。

当整个存储容量不足时,可以添加一个或多个 卷以扩展存储容量。为此,您需要添加一个或 更多存储服务器。

FastDFS 中的文件标识分为两个部分:卷名和文件名,二者缺一不可。

FastDFS file upload

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

FastDFS file download

下载文件交互过程:

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

需要说明的是,client 为使用 FastDFS 服务的调用方,client 也应该是一台服务器,它对 tracker 和 storage 的调用均为服务器间的调用。

2、使用的系统软件

名称

说明

centos

7.x

libfastcommon

FastDFS分离出的公用函数库

libserverframe

FastDFS分离出的网络框架

FastDFS

FastDFS本体

fastdfs-nginx-module

FastDFS和nginx的关联模块

nginx

nginx1.15.4

FastDFS下载地址:https://sourceforge.net/projects/fastdfs/

FastDFS的github下载地址:https://github.com/happyfish100/fastdfs

libfastcommon的下载地址:https://sourceforge.net/projects/libfastcommon/

libfastcommon的github下载地址:https://github.com/happyfish100/libfastcommon

FastDFS-nginx-module的github下载地址:GitHub - happyfish100/fastdfs-nginx-module: FastDFS nginx module

二、部署

1、yum安装

1.1yum源安装

CentOS 7、RHEL 7、Oracle Linux 7、Alibaba Cloud Linux 2、Anolis 7、AlmaLinux 7、Amazon Linux 2、Fedora 27及以下版本:

rpm -ivh http://www.fastken.com/yumrepo/el7/noarch/FastOSrepo-1.0.0-1.el7.centos.noarch.rpm

CentOS 8、Rocky 8、RHEL 8、Oracle Linux 8、Alibaba Cloud Linux 3、Anolis 8、AlmaLinux 8、Amazon Linux 3、Fedora 28及以上版本:

rpm -ivh http://www.fastken.com/yumrepo/el8/noarch/FastOSrepo-1.0.0-1.el8.noarch.rpm

安装 FastDFS软件包:

yum install fastdfs-server fastdfs-tool fastdfs-config -y

2、编译环境

CentOS

yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y

3、磁盘目录

说明

位置

所有安装包

/usr/local/src

数据存储位置

/home/dfs/

#这里我为了方便把日志什么的都放到了dfs

mkdir /home/dfs #创建数据存储目录 cd /usr/local/src #切换到安装目录准备下载安装包

4、 安装libfastcommon

git clone https://github.com/happyfish100/libfastcommon.git --depth 1
cd libfastcommon/
./make.sh && ./make.sh install #编译安装
cd ../ #返回上一级目录

5、安装libserverframe

git clone https://github.com/happyfish100/libserverframe.git --depth 1
cd libserverframe/
./make.sh && ./make.sh install #编译安装
cd ../ #返回上一级目录

6、安装FastDFS

git clone https://github.com/happyfish100/fastdfs.git --depth 1
cd fastdfs/
./make.sh && ./make.sh install #编译安装
#配置文件准备
cp /usr/local/src/fastdfs/conf/http.conf /etc/fdfs/ #供nginx访问使用
cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs/ #供nginx访问使用
cd ../ #返回上一级目录

7、安装fastdfs-nginx-module

git clone https://github.com/happyfish100/fastdfs-nginx-module.git --depth 1
cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs

8、安装nginx

wget http://nginx.org/download/nginx-1.15.4.tar.gz #下载nginx压缩包
tar -zxvf nginx-1.15.4.tar.gz #解压
cd nginx-1.15.4/
#添加fastdfs-nginx-module模块
./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ 
make && make install #编译安装

三、单机部署

1、tracker配置

#服务器ip为 192.168.52.1
#我建议用ftp下载下来这些文件 本地修改
vim /etc/fdfs/tracker.conf
#需要修改的内容如下
port=22122  # tracker服务器端口(默认22122,一般不修改)
base_path=/home/dfs  # 存储日志和数据的根目录

2、storage配置

vim /etc/fdfs/storage.conf
#需要修改的内容如下
port=23000  # storage服务端口(默认23000,一般不修改)
base_path=/home/dfs  # 数据和日志文件存储根目录
store_path0=/home/dfs  # 第一个存储目录
tracker_server=192.168.52.1:22122  # tracker服务器IP和端口
http.server_port=8888  # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)

3、client测试

vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/home/dfs
tracker_server=192.168.52.1:22122    #tracker服务器IP和端口
#保存后测试,返回ID表示成功 如:group1/M00/00/00/xx.tar.gz
fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/nginx-1.15.4.tar.gz

4、配置nginx访问

vim /etc/fdfs/mod_fastdfs.conf
#需要修改的内容如下
tracker_server=192.168.52.1:22122  #tracker服务器IP和端口
url_have_group_name=true
store_path0=/home/dfs
#配置nginx.config
vim /usr/local/nginx/conf/nginx.conf
#添加如下配置
server {
    listen       8888;    ## 该端口为storage.conf中的http.server_port相同
    server_name  localhost;
    location ~/group[0-9]/ {
        ngx_fastdfs_module;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
    root   html;
    }
}
#测试下载,用外部浏览器访问刚才已传过的nginx安装包,引用返回的ID
http://192.168.52.1:8888/group1/M00/00/00/wKgAQ1pysxmAaqhAAA76tz-dVgg.tar.gz
#弹出下载单机部署全部跑通

四、分布式部署

tracker配置

#服务器ip为 192.168.52.2,192.168.52.3,192.168.52.4
#我建议用ftp下载下来这些文件 本地修改
vim /etc/fdfs/tracker.conf
#需要修改的内容如下
port=22122  # tracker服务器端口(默认22122,一般不修改)
base_path=/home/dfs  # 存储日志和数据的根目录

storage配置

vim /etc/fdfs/storage.conf
#需要修改的内容如下
port=23000  # storage服务端口(默认23000,一般不修改)
base_path=/home/dfs  # 数据和日志文件存储根目录
store_path0=/home/dfs  # 第一个存储目录
tracker_server=192.168.52.2:22122  # 服务器1
tracker_server=192.168.52.3:22122  # 服务器2
tracker_server=192.168.52.4:22122  # 服务器3
http.server_port=8888  # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)

client测试

vim /etc/fdfs/client.conf
#需要修改的内容如下
base_path=/home/moe/dfs
tracker_server=192.168.52.2:22122  # 服务器1
tracker_server=192.168.52.3:22122  # 服务器2
tracker_server=192.168.52.4:22122  # 服务器3
#保存后测试,返回ID表示成功 如:group1/M00/00/00/xx.tar.gz
fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/nginx-1.15.4.tar.gz

配置nginx访问

vim /etc/fdfs/mod_fastdfs.conf
#需要修改的内容如下
tracker_server=192.168.52.2:22122  # 服务器1
tracker_server=192.168.52.3:22122  # 服务器2
tracker_server=192.168.52.4:22122  # 服务器3
url_have_group_name=true
store_path0=/home/dfs
#配置nginx.config
vim /usr/local/nginx/conf/nginx.conf
#添加如下配置
server {
    listen       8888;    ## 该端口为storage.conf中的http.server_port相同
    server_name  localhost;
    location ~/group[0-9]/ {
        ngx_fastdfs_module;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
    root   html;
    }
}

五、启动

防火墙

#不关闭防火墙的话无法使用
systemctl stop firewalld.service #关闭
systemctl restart firewalld.service #重启

tracker

修改 /usr/lib/systemd/system/fdfs_trackerd.service 中的 PIDFile,格式为:
PIDFile=$base_path/data/fdfs_trackerd.pid
比如:
PIDFile=/home/dfs/data/fdfs_trackerd.pid

systemctl start fdfs_trackerd #启动tracker服务
systemctl restart fdfs_trackerd #重启动tracker服务
systemctl stop fdfs_trackerd #停止tracker服务
systemctl enable fdfs_trackerd  #开机自启动

storage

修改 /usr/lib/systemd/system/fdfs_storaged.service 中的 PIDFile,格式为:
PIDFile=$base_path/data/fdfs_storaged.pid
比如:
PIDFile=/home/dfs/data/fdfs_storaged.pid

systemctl start fdfs_storaged #启动storage服务
systemctl restart fdfs_storaged  #重动storage服务
systemctl stop fdfs_storaged  #停止动storage服务
systemctl enable fdfs_storaged   #开机自启动

nginx

/usr/local/nginx/sbin/nginx #启动nginx
/usr/local/nginx/sbin/nginx -s reload #重启nginx
/usr/local/nginx/sbin/nginx -s stop #停止nginx

检测集群

/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
# 会显示会有几台服务器 有3台就会 显示 Storage 1-Storage 3的详细信息

配置文件

tracker_server #有几台服务器写几个
group_name #地址的名称的命名
bind_addr #服务器ip绑定
store_path_count #store_path(数字)有几个写几个
store_path(数字) #设置几个储存地址写几个 从0开始

可能遇到的问题

如果不是root 用户 你必须在除了cd的命令之外 全部加sudo
如果不是root 用户 编译和安装分开进行 先编译再安装
如果上传成功 但是nginx报错404 先检查mod_fastdfs.conf文件中的store_path0是否一致
如果nginx无法访问 先检查防火墙 和 mod_fastdfs.conf文件tracker_server是否一致
如果不是在/usr/local/src文件夹下安装 可能会编译出错
如果 unknown directive "ngx_fastdfs_module" in /usr/local/nginx/conf/nginx.conf:151,可能是nginx一直是启动的,必须要重启nginx才可以,`nginx -s reload`无效。
如果nginx的error.log中提示:ERROR - file: ini_file_reader.c, line: 1051, include file "http.conf" not exists, line: "#include http.conf"
ERROR - file: /root/fastdfs-nginx-module/src/common.c, line: 163, load conf file "/etc/fdfs/mod_fastdfs.conf" fail, ret code: 2
则 需要将fastdfs的源码中的conf文件夹中的http.conf和mime.types cp到 etc/fdf文件夹中。

六、Java整合

1、下载fastdfs-client-java官方源码:

GitHub - happyfish100/fastdfs-client-java: FastDFS java client SDK

2、使用maven从源码安装

mvn clean install

3、在您的maven项目pom.xml中添加依赖

<dependency>
    <groupId>org.csource</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.30-SNAPSHOT</version>
</dependency>

4、.conf 配置文件、所在目录、加载优先顺序

配置文件名fdfs_client.conf(或使用其它文件名xxx_yyy.conf)

文件所在位置可以是项目classpath(或OS文件系统目录比如/opt/):
/opt/fdfs_client.conf
C:\Users\James\config\fdfs_client.conf

优先按OS文件系统路径读取,没有找到才查找项目classpath,尤其针对linux环境下的相对路径比如:
fdfs_client.conf
config/fdfs_client.conf

connect_timeout = 2
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 80
http.anti_steal_token = no
http.secret_key = FastDFS1234567890

tracker_server = 10.0.11.247:22122
tracker_server = 10.0.11.248:22122
tracker_server = 10.0.11.249: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

注1:tracker_server指向您自己IP地址和端口,1-n个
注2:除了tracker_server,其它配置项都是可选的

开发时将配置文件fdfs_client.conf 拷贝到项目中的resources目录下

5、.properties 配置文件、所在目录、加载优先顺序

配置文件名 fastdfs-client.properties(或使用其它文件名 xxx-yyy.properties)

文件所在位置可以是项目classpath(或OS文件系统目录比如/opt/):
/opt/fastdfs-client.properties
C:\Users\James\config\fastdfs-client.properties

优先按OS文件系统路径读取,没有找到才查找项目classpath,尤其针对linux环境下的相对路径比如:
fastdfs-client.properties
config/fastdfs-client.properties

fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30
fastdfs.charset = UTF-8
fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80

fastdfs.tracker_servers = 10.0.11.201:22122,10.0.11.202:22122,10.0.11.203:22122

fastdfs.connection_pool.enabled = true
fastdfs.connection_pool.max_count_per_entry = 500
fastdfs.connection_pool.max_idle_time = 3600
fastdfs.connection_pool.max_wait_time_in_ms = 1000

 注1:properties 配置文件中属性名跟 conf 配置文件不尽相同,并且统一加前缀"fastdfs.",便于整合到用户项目配置文件
注2:fastdfs.tracker_servers 配置项不能重复属性名,多个 tracker_server 用逗号","隔开
注3:除了fastdfs.tracker_servers,其它配置项都是可选的

6、开发示例

public class FastDFSFile {

    /**
     * 文件名字
     */
    private String name;

    /**
     * 文件内容
     */
    private byte[] content;

    /**
     * 文件扩展名
     */
    private String ext;

    /**
     * 文件MD5摘要值
     */
    private String md5;

    /**
     * 文件创建作者
     */
    private String author;

    public FastDFSFile(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 FastDFSFile(String name, byte[] content, String ext) {
        super();
        this.name = name;
        this.content = content;
        this.ext =ext;
    }
}

public class FastDFSClient {
    private static Logger logger = LoggerFactory.getLogger(FastDFSFile.class);

    /**
     * 初始化加载 FastDFS的TrackerServer配置
     */
    static {
        try {
            String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
            ClientGlobal.init(filePath);
        } catch (Exception e) {
            logger.error("FastDFS 初始化失败", 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("上传文件失败: " + file.getName(), e);
        }

        if (uploadResults ==null && storageClient != null) {
            logger.error("上传文件错误,错误码: " + 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("从FastDFS中获取文件错误", 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);
            ByteArrayInputStream ins = new ByteArrayInputStream(fileByte);
            return ins;
        } catch (Exception e) {
            logger.error("从FastDFS获取文件失败", e);
        }
        return null;
    }

    /**
     * 文件删除
     * @param groupName
     * @param remoteFileName
     */
    public static  void deleteFile(String groupName, String remoteFileName) {
        try {
            // 创建 StorageClient
            StorageClient storageClient = getTrackerClient();
            // 删除文件
            int i = storageClient.delete_file(groupName, remoteFileName);
        } catch (Exception e) {
            logger.error("从FastDFS中文件删除失败", e);
        }
    }

    /**
     * 获取Storage组
     * @param groupName 组名
     * @return
     */
    public static StorageServer[] getStoreStorages(String groupName) {
        try {
            // 创建 TrackerClient
            TrackerClient trackerClient = new TrackerClient();
            // 获取 TrackerServer
            TrackerServer trackerServer = trackerClient.getConnection();
            //获取 Storage 组
            return trackerClient.getStoreStorages(trackerServer, groupName);
        } catch (Exception e) {
            logger.error("从FastDFS获取Storage 组失败", e);
        }
        return null;
    }

    /**
     * 获取 Storage 信息,IP和端口
     * @param groupName
     * @param remoteFileName
     * @return
     */
    public static ServerInfo[] getFetchStoages(String groupName, String remoteFileName) {
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
        } catch (Exception e) {
           logger.error("获取Storage信息,IP 和端口失败", e);
        }
        return null;
    }

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

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

    /**
     * 获取 Tracker
     * @return
     */
    private static TrackerServer getTrackerServer() {
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            return trackerServer;
        } catch (Exception e) {
            logger.error("获取Tracker 失败", e);
        }
        return null;
    }
}


@PostMapping("upload")
public Result upload(MultipartFile file) {
    try {
        // 文件上传
        // 1. 获取文件属性
        // 1.1. 原始文件名
        String originalFilename = file.getOriginalFilename();
        // 1.2. 文件内容
        byte[] fileBytes = file.getBytes();
        // 1.3 文件扩展名  test.jpg -> jpg
        String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);

        // 2. 创建 FastDFSFile
        FastDFSFile fastDFSFile = new FastDFSFile(originalFilename, fileBytes, ext);
        // 3. 调用工具类上传
        // uploadResult 第一个只是 group 第二个值是:物理路径
        String[] uploadResult = FastDFSClient.upload(fastDFSFile);

        // 预览url
        String url = FastDFSClient.getTrackerUrl() + uploadResult[0] + "/" + uploadResult[1];

        return new Result(true, StatusCode.OK, "上传成功",url);
    } catch (Exception e) {
        return new Result(false, StatusCode.ERROR, "上传失败" + e.getMessage());
    }
}

@PostMapping("upload")
public Result upload(String local_filename,String conf_filename ) {
      
        String group_name;

        try {
            ClientGlobal.init(conf_filename);
            System.out.println("network_timeout=" + ClientGlobal.g_network_timeout + "ms");
            System.out.println("charset=" + ClientGlobal.g_charset);

            String file_id;

            TrackerClient tracker = new TrackerClient();
            TrackerServer trackerServer = tracker.getTrackerServer();

            StorageServer storageServer = null;
      /*
      storageServer = tracker.getStoreStorage(trackerServer);
  		if (storageServer == null)
  		{
  			System.out.println("getStoreStorage fail, error code: " + tracker.getErrorCode());
  			return;
  		}
  		*/
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);
            byte[] file_buff;
            NameValuePair[] meta_list;
            String master_file_id;
            String prefix_name;
            String file_ext_name;
            String slave_file_id;
            String generated_slave_file_id;
            int errno;

            group_name = "group1";
            StorageServer[] storageServers = tracker.getStoreStorages(trackerServer, group_name);
            if (storageServers == null) {
                System.err.println("get store storage servers fail, error code: " + tracker.getErrorCode());
            } else {
                System.err.println("store storage servers count: " + storageServers.length);
                for (int k = 0; k < storageServers.length; k++) {
                    System.err.println((k + 1) + ". " + storageServers[k].getInetSocketAddress().getAddress().getHostAddress() + ":" + storageServers[k].getInetSocketAddress().getPort());
                }
                System.err.println("");
            }

            meta_list = new NameValuePair[4];
            meta_list[0] = new NameValuePair("width", "800");
            meta_list[1] = new NameValuePair("heigth", "600");
            meta_list[2] = new NameValuePair("bgcolor", "#FFFFFF");
            meta_list[3] = new NameValuePair("author", "Mike");

            file_buff = "this is a test".getBytes(ClientGlobal.g_charset);
            System.out.println("file length: " + file_buff.length);

            file_id = client.upload_file1(file_buff, "txt", meta_list);
  		/*
  		group_name = "group1";
  		file_id = client.upload_file1(group_name, file_buff, "txt", meta_list);
  		*/
            if (file_id == null) {
                System.err.println("upload file fail, error code: " + client.getErrorCode());
                return;
            } else {
                System.err.println("file_id: " + file_id);
                System.err.println(client.get_file_info1(file_id));

                ServerInfo[] servers = tracker.getFetchStorages1(trackerServer, file_id);
                if (servers == null) {
                    System.err.println("get storage servers fail, error code: " + tracker.getErrorCode());
                } else {
                    System.err.println("storage servers count: " + servers.length);
                    for (int k = 0; k < servers.length; k++) {
                        System.err.println((k + 1) + ". " + servers[k].getIpAddr() + ":" + servers[k].getPort());
                    }
                    System.err.println("");
                }

                meta_list = new NameValuePair[4];
                meta_list[0] = new NameValuePair("width", "1024");
                meta_list[1] = new NameValuePair("heigth", "768");
                meta_list[2] = new NameValuePair("bgcolor", "#000000");
                meta_list[3] = new NameValuePair("title", "Untitle");

                if ((errno = client.set_metadata1(file_id, meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE)) == 0) {
                    System.err.println("set_metadata success");
                } else {
                    System.err.println("set_metadata fail, error no: " + errno);
                }

                meta_list = client.get_metadata1(file_id);
                if (meta_list != null) {
                    for (int i = 0; i < meta_list.length; i++) {
                        System.out.println(meta_list[i].getName() + " " + meta_list[i].getValue());
                    }
                }

                //Thread.sleep(30000);

                file_buff = client.download_file1(file_id);
                if (file_buff != null) {
                    System.out.println("file length:" + file_buff.length);
                    System.out.println((new String(file_buff)));
                }

                master_file_id = file_id;
                prefix_name = "-part1";
                file_ext_name = "txt";
                file_buff = "this is a slave buff.".getBytes(ClientGlobal.g_charset);
                slave_file_id = client.upload_file1(master_file_id, prefix_name, file_buff, file_ext_name, meta_list);
                if (slave_file_id != null) {
                    System.err.println("slave file_id: " + slave_file_id);
                    System.err.println(client.get_file_info1(slave_file_id));

                    generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name);
                    if (!generated_slave_file_id.equals(slave_file_id)) {
                        System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id);
                    }
                }

                //Thread.sleep(10000);
                if ((errno = client.delete_file1(file_id)) == 0) {
                    System.err.println("Delete file success");
                } else {
                    System.err.println("Delete file fail, error no: " + errno);
                }
            }

            if ((file_id = client.upload_file1(local_filename, null, meta_list)) != null) {
                int ts;
                String token;
                String file_url;
                InetSocketAddress inetSockAddr;

                System.err.println("file_id: " + file_id);
                System.err.println(client.get_file_info1(file_id));

                inetSockAddr = trackerServer.getInetSocketAddress();
                file_url = "http://" + inetSockAddr.getAddress().getHostAddress();
                if (ClientGlobal.g_tracker_http_port != 80) {
                    file_url += ":" + ClientGlobal.g_tracker_http_port;
                }
                file_url += "/" + file_id;
                if (ClientGlobal.g_anti_steal_token) {
                    ts = (int) (System.currentTimeMillis() / 1000);
                    token = ProtoCommon.getToken(file_id, ts, ClientGlobal.g_secret_key);
                    file_url += "?token=" + token + "&ts=" + ts;
                }
                System.err.println("file url: " + file_url);

                errno = client.download_file1(file_id, 0, 100, "c:\\" + file_id.replaceAll("/", "_"));
                if (errno == 0) {
                    System.err.println("Download file success");
                } else {
                    System.err.println("Download file fail, error no: " + errno);
                }

                errno = client.download_file1(file_id, new DownloadFileWriter("c:\\" + file_id.replaceAll("/", "-")));
                if (errno == 0) {
                    System.err.println("Download file success");
                } else {
                    System.err.println("Download file fail, error no: " + errno);
                }

                master_file_id = file_id;
                prefix_name = "-part2";
                file_ext_name = null;
                slave_file_id = client.upload_file1(master_file_id, prefix_name, local_filename, file_ext_name, meta_list);
                if (slave_file_id != null) {
                    System.err.println("slave file_id: " + slave_file_id);
                    System.err.println(client.get_file_info1(slave_file_id));

                    generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name);
                    if (!generated_slave_file_id.equals(slave_file_id)) {
                        System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id);
                    }
                }
            }

            File f;
            f = new File(local_filename);
            int nPos = local_filename.lastIndexOf('.');
            if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) {
                file_ext_name = local_filename.substring(nPos + 1);
            } else {
                file_ext_name = null;
            }

            file_id = client.upload_file1(null, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list);
            if (file_id != null) {
                System.out.println("file id: " + file_id);
                System.out.println(client.get_file_info1(file_id));
                master_file_id = file_id;
                prefix_name = "-part3";
                slave_file_id = client.upload_file1(master_file_id, prefix_name, f.length(), new UploadLocalFileSender(local_filename), file_ext_name, meta_list);
                if (slave_file_id != null) {
                    System.err.println("slave file_id: " + slave_file_id);
                    generated_slave_file_id = ProtoCommon.genSlaveFilename(master_file_id, prefix_name, file_ext_name);
                    if (!generated_slave_file_id.equals(slave_file_id)) {
                        System.err.println("generated slave file: " + generated_slave_file_id + "\n != returned slave file: " + slave_file_id);
                    }
                }
            } else {
                System.err.println("Upload file fail, error no: " + errno);
            }

            storageServer = tracker.getFetchStorage1(trackerServer, file_id);
            if (storageServer == null) {
                System.out.println("getFetchStorage fail, errno code: " + tracker.getErrorCode());
                return;
            }


            /* for test only */
            System.out.println("active test to storage server: " + storageServer.getConnection().activeTest());

            /* for test only */
            System.out.println("active test to tracker server: " + trackerServer.getConnection().activeTest());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }turn new Result(false, StatusCode.ERROR, "上传失败" + e.getMessage());
    }
}
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值