一、概述
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());
}
}