本示例主要介绍一个单机的 FastDFS 服务,然后通过 Java 程序去连接,实现文件的上传、下载。
在开始本实例之前,需要先准备好一个 Linux 的虚拟机,本实例使用的是 CentOS-7-Minimal-1810。
大纲
一、先安装 FastDFS 服务
1、安装运行环境依赖
2、下载安装包
3、解压安装
4、配置
5、启动服务,检查是正成功
二、编写 Java Client
1、准备测试文件
2、准备 Client 配置
3、下载 Jar 包
4、编写实例代码
5、运行测试
开始
安装依赖
yum -y install gcc gcc-c++ libstdc++-devel pcre-devel zlib-devel wget make net-tools
yum -y groupinstall 'Development Tools'
下载 fastdfs 包
cd /usr/local/
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.7.tar.gz
wget https://github.com/happyfish100/fastdfs/archive/V5.05.tar.gz
解压安装
tar -zxvf V1.0.7.tar.gz
tar -zxvf V5.05.tar.gz
cd libfastcommon-1.0.7
./make.sh
./make.sh install
cd ../fastdfs-5.05
./make.sh
./make.sh install
######## 以下配置用于配置 tracker ##################
创建存储配置数据的目录。
mkdir -p /usr/local/fastdfs/tracker
复制配置文件,修改配置
cd /etc/fdfs
cp tracker.conf.sample tracker.conf
vim tracker.conf
修改配置数据目录,及端口。
base_path=/usr/local/fastdfs/tracker
打开防火墙端口
firewall-cmd --permanent --zone=public --add-port=22122/tcp
firewall-cmd --reload
启动 tracker 服务
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
使用命令查看是否启动成功
ps -ef|grep fdfs
# 正常结果
root 6078 1 0 11:59 ? 00:00:00 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
root 6101 6054 0 12:01 pts/2 00:00:00 grep fdfs
#####################
以下配置用于配置 storage
#####################
创建存储配置数据的目录。
mkdir -p /usr/local/fastdfs/storage
复制配置文件,修改配置
cd /etc/fdfs
cp storage.conf.sample storage.conf
vim storage.conf
修改配置
base_path=/usr/local/fastdfs/storage
store_path0=/usr/local/fastdfs/storage
tracker_server=192.168.3.5:22122
打开防火墙端口
firewall-cmd --permanent --zone=public --add-port=23000/tcp
firewall-cmd --reload
启动 storage 服务
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
查看是否启动成功
netstat -unltp | grep fdfs
# 正常结果
tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 19947/fdfs_trackerd
tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 20073/fdfs_storaged
#################
下面开始 Java Client
#################
maven
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>
config.properties 配置文件
D:\config.properties
tracker_server=192.168.11.128:22122
准备一个用于上传的测试文件
D:\a.jpg
## Java 代码
package com.yy.web.service.fastdfs;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
public class FastDFSClient {
private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;
public static void main(String[] args) throws Exception {
FastDFSClient dfs = new FastDFSClient("D:\\config.properties");
// 上传。
String uploadFile = dfs.upload("D:\\a.jpg");
System.out.println(uploadFile);
// 下载。
byte[] downloadBytes = dfs.download(uploadFile);
save(new File("D:\\b.jpg"), downloadBytes);
// // 删除。
// int deleted = dfs.delete(uploadFile);
// System.out.println(deleted);
}
public FastDFSClient(String conf) throws Exception {
ClientGlobal.init(conf);
trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
trackerServer = trackerClient.getConnection();
if (trackerServer == null) {
throw new IllegalStateException("getConnection return null");
}
storageServer = trackerClient.getStoreStorage(trackerServer);
if (storageServer == null) {
throw new IllegalStateException("getStoreStorage return null");
}
storageClient = new StorageClient1(trackerServer, storageServer);
}
/**
* 上传文件方法
*
* @param file
* 文件全路径
* @return
* @throws Exception
*/
public String upload(String file) {
String result = null;
try {
result = storageClient.upload_file1(file, null, null);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return result;
}
/**
* 获取文件数组
*
* @param path
* 文件的路径 如group1/M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
* @return
*/
public byte[] download(String path) {
byte[] bytes = null;
try {
bytes = storageClient.download_file1(path);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return bytes;
}
/**
* @param storagePath
* 文件的全部路径 如:group1/M00/00/00/wKgRsVjtwpSAXGwkAAAweEAzRjw471.jpg
*
* @return -1失败,0成功
* @throws IOException
* @throws Exception
*/
public Integer delete(String storagePath) {
int result = -1;
try {
result = storageClient.delete_file1(storagePath);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
return result;
}
public static boolean save(File file, byte[] content) throws IOException {
boolean isSuccess = false;
FileOutputStream out = null;
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
try {
out = new FileOutputStream(file);
out.write(content);
out.flush();
isSuccess = true;
} finally {
if (out != null) {
out.close();
}
}
return isSuccess;
}
}
执行成功结果
完成
该实例演示一个精简的 FastDFS 使用,没有集成 Nginx 服务,因为我后续需要对资源的访问做权限控制,所以这里获取 byte[] 数据就够了
遇到的问题:
本地开发环境 + 本地虚拟机,这样连接的话不会有问题。如果本地开发环境 + (云 Nginx 服务器代理 2212、2300 端口 + FastDFS 服务器),这种模式下, Storage 的 tracker_server 配置要写成公网的地址,不然 Socket Connection timeout。
遇到这个问题,是因为 tracker 返回给 client 的是 storage 的连接地址,但该连接地址其实是内部网络,所以 client 使用返回的 storage 地址时就无法连接。