FastDFS安装并 spring 集成(包含 Nginx)

第一次写博客,不好之处请见谅

直入主题:
FastDFS 分布式文件系统的安装与使用(单节点)


服务器地址

跟踪服务器:120.77.41.37
存储服务器:120.77.41.37

服务器环境

环境:CentOS 7
用户: root
数据目录:/fastdfs (注:数据目录按你的数据盘挂载路径而定)

安装包

FastDFS v5.05
libfastcommon-master.zip(是从 FastDFS 和 FastDHT 中提取出来的公共 C 函数库)
fastdfs-nginx-module_v1.16.tar.gz
nginx-1.6.2.tar.gz
fastdfs_client_java._v1.25.tar.gz
源码地址:https://github.com/happyfish100/
下载地址:http://sourceforge.net/projects/fastdfs/files/
官方论坛:http://bbs.chinaunix.net/forum-240-1.html

所有跟踪服务器和存储服务器均执行如下操作:

####编译和安装所需的依赖包:

# yum install make cmake gcc gcc-c++

####安装 libfastcommon:

  • 上传或下载 libfastcommon-master.zip 到/usr/local/src 目录
  • 解压:

# cd /usr/local/src/
# unzip libfastcommon-master.zip
# cd libfastcommon-master

  • 编译、安装:

# ./make.sh
# ./make.sh install
libfastcommon 默认安装到了
/usr/lib64/libfastcommon.so
/usr/lib64/libfdfsclient.so

  • 因为 FastDFS 主程序设置的 lib 目录是/usr/local/lib,所以需要创建软链接:

# ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
# ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so
# ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
# ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so
####安装 FastDFS

  • 上传或下载 FastDFS 源码包(FastDFS_v5.05.tar.gz)到 /usr/local/src 目录
  • 解压:

# cd /usr/local/src/
# tar -zxvf FastDFS_v5.05.tar.gz
# cd FastDFS

  • 编译、安装(编译前要确保已经成功安装了 libfastcommon)

# ./make.sh
# ./make.sh install
采用默认安装的方式安装,安装后的相应文件与目录:
A、服务脚本在:
/etc/init.d/fdfs_storaged
/etc/init.d/fdfs_tracker
B、配置文件在(样例配置文件):
/etc/fdfs/client.conf.sample
/etc/fdfs/storage.conf.sample
/etc/fdfs/tracker.conf.sample
C、命令工具在/usr/bin/目录下的:
fdfs_appender_test
fdfs_appender_test1
fdfs_append_file
fdfs_crc32

  • 因为 FastDFS 服务脚本设置的 bin 目录是/usr/local/bin,但实际命令安装在/usr/bin,可以进入 /user/bin 目录使用以下命令查看 fdfs 的相关命令:

# cd /usr/bin/
# ls | grep fdfs

  • 因此需要修改 FastDFS 服务脚本中相应的命令路径,也就是把/etc/init.d/fdfs_storaged 和/etc/init.d/fdfs_tracker 两个脚本中的/usr/local/bin 修改成/usr/bin:

# vi fdfs_trackerd

  • 使用查找替换命令进统一修改:%s+/usr/local/bin+/usr/bin

# vi fdfs_storaged

  • 使用查找替换命令进统一修改:%s+/usr/local/bin+/usr/bin

配置 FastDFS 跟踪器

复制 FastDFS 跟踪器样例配置文件,并重命名:

# cd /etc/fdfs/
# cp tracker.conf.sample tracker.conf

编辑跟踪器配置文件:

# vi /etc/fdfs/tracker.conf

修改的内容如下:

disabled=false
port=22122
base_path=/fastdfs/tracker
(其它参数保留默认配置,具体配置解释请参考官方文档说明: http://bbs.chinaunix.net/thread-1941456-1-1.html )

创建基础数据目录(参考基础目录 base_path 配置):

# mkdir -p /fastdfs/tracker

防火墙中打开跟踪器端口(默认为 22122):

# vi /etc/sysconfig/iptables

添加如下端口行:
   -A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT
重启防火墙:

# service iptables restart

启动 Tracker:

# /etc/init.d/fdfs_trackerd star

(初次成功启动,会在/fastdfs/tracker 目录下创建 data、logs 两个目录)
查看 FastDFS Tracker 是否已成功启动:

# ps -ef | grep fdfs

关闭 Tracker:

# /etc/init.d/fdfs_trackerd stop

设置 FastDFS 跟踪器开机启动:

# vi /etc/rc.d/rc.local

添加以下内容:

## FastDFS Tracker
/etc/init.d/fdfs_trackerd start


配置 FastDFS 存储

复制 FastDFS 存储器样例配置文件,并重命名:

# cd /etc/fdfs/
# cp storage.conf.sample storage.conf

编辑存储器样例配置文件:

# vi /etc/fdfs/storage.conf

修改的内容如下:

disabled=false
port=23000
base_path=/fastdfs/storage
store_path0=/fastdfs/storage
tracker_server=120.77.41.37:22122
http.server_port=8888
(其它参数保留默认配置,具体配置解释请参考官方文档说明: http://bbs.chinaunix.net/thread-1941456-1-1.html )

创建基础数据目录(参考基础目录 base_path 配置):

# mkdir -p /fastdfs/storage

防火墙中打开存储器端口(默认为 23000):

参考上面修改防火墙

启动 Storage:

# /etc/init.d/fdfs_storaged start

初次成功启动,会在/fastdfs/storage 目录下创建 data、logs 两个目录)

关闭 Storage:

# /etc/init.d/fdfs_storaged stop

设置 FastDFS 存储器开机启动:

# vi /etc/rc.d/rc.local

添加:

## FastDFS Storage
/etc/init.d/fdfs_storaged start


四、文件上传测试

修改 Tracker 服务器中的客户端配置文件:

# cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
# vi /etc/fdfs/client.conf
修改内容如下:
base_path=/fastdfs/tracker
btracker_server=120.77.41.37:22122

执行如下文件上传命令:

# /usr/bin/fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/FastDFS_v5.05.tar.gz

返回 ID 号:group1/M00/00/00/wKFHOASIOCO43242342XO.tar.gz
能返回以上文件 ID,说明文件上传成功)

在每个存储节点上安装 nginx

fastdfs-nginx-module 作用说明:

FastDFS 通过 Tracker 服务器,将文件放在 Storage 服务器存储,但是同组存储服务器之间需要进入文件复制,有同步延迟的问题。假设 Tracker 服务器将文件上传到了 120.77.41.37,上传成功后文件 ID 已经返回给客户端。此时 FastDFS 存储集群机制会将这个文件同步到同组存储 120.77.41.37,在文件还 没有复制完成的情况下,客户端如果用这个文件 ID 在 120.77.41.37 上取文件,就会出现文件无法访问的 错误。而 fastdfs-nginx-module 可以重定向文件连接到源服务器取文件,避免客户端由于复制延迟导致的 文件无法访问错误。(解压后的 fastdfs-nginx-module 在 nginx 安装时使用)

上传 fastdfs-nginx-module_v1.16.tar.gz 到/usr/local/src

解压

# cd /usr/local/src/
# tar -zxvf fastdfs-nginx-module_v1.16.tar.gz

修改 fastdfs-nginx-module 的 config 配置文件:

# cd fastdfs-nginx-module/src
# vi config
CORE_INCS=“ C O R E I N C S / u s r / l o c a l / i n c l u d e / f a s t d f s / u s r / l o c a l / i n c l u d e / f a s t c o m m o n / " < / f o n t > 修 改 为 : < f o n t c o l o r = " g r e e n " s i z e = " 1 p x " > C O R E I N C S = " CORE_INCS /usr/local/include/fastdfs /usr/local/include/fastcommon/" 修改为: CORE_INCS=" COREINCS/usr/local/include/fastdfs/usr/local/include/fastcommon/"</font>:<fontcolor="green"size="1px">COREINCS="CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/”
注意:这个路径修改是很重要的,不然在 nginx 编译的时候会报错的)

上传当前的稳定版本 Nginx(nginx-1.6.2.tar.gz)到/usr/local/src 目录:

安装编译 Nginx 所需的依赖包:

# yum install gcc gcc-c++ make automake autoconf libtool pcre* zlib openssl openssl-devel

编译安装 Nginx(添加 fastdfs-nginx-module 模块):

# cd /usr/local/src/
# tar -zxvf nginx-1.6.2.tar.gz
# cd nginx-1.6.2
# ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src
# make && make install

复制 fastdfs-nginx-module 源码中的配置文件到/etc/fdfs 目录,并修改:

# cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/
# vi /etc/fdfs/mod_fastdfs.conf
修改以下配置:
connect_timeout=10
base_path=/tmp
tracker_server=120.77.41.37:22122
storage_server_port=23000
group_name=group1
url_have_group_name = true
store_path0=/fastdfs/storage

复制 FastDFS 的部分配置文件到/etc/fdfs 目录:

# cd /usr/local/src/FastDFS/conf
# cp http.conf mime.types /etc/fdfs/

在/fastdfs/storage 文件存储目录下创建软连接,将其链接到实际存放数据的目录:

# ln -s /fastdfs/storage/data/ /fastdfs/storage/data/M00

配置 Nginx:

简洁版 nginx 配置样例:

user root;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8888;
server_name localhost;
location ~/group([0-9])/M00 {
#alias /fastdfs/storage/data;
ngx_fastdfs_module;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html; }
} }

A、8888 端口值是要与/etc/fdfs/storage.conf 中的 http.server_port=8888 相对应,因为 http.server_port 默认为 8888,如果想改成 80,则要对应修改过来。
B、Storage 对应有多个 group 的情况下,访问路径带 group 名,如/group1/M00/00/00/xxx,

对应的 Nginx 配置为:

location ~/group([0-9])/M00 {
ngx_fastdfs_module;
}

C、如查下载时如发现老报 404,将 nginx.conf 第一行 user nobody 修改为 user root 后重新启动。

防火墙中打开 Nginx 的 8888 端口

参考前边修改防火墙端口

启动 Nginx:

# /usr/local/nginx/sbin/nginx
ngx_http_fastdfs_set pid=xxx
(重启 Nginx 的命令为:/usr/local/nginx/sbin/nginx -s reload)

通过浏览器访问测试时上传的文件:

http://120.77.41.37:8888/group1/M00/00/00/rBIvKFll_-iAKwK9AAIpzOP593E159.jpg?token=f42b765ca5101374e831b123ce4f8fbe&ts=1499856871

浏览器成功访问

![上传成功](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwNzEzMTA0MzE3MDU


FastDFS与 Spring 整合

xml配置文件:

<bean id="fastDFSFactory" class="com.anniweiya.fastdfs.FastDFSTemplateFactory" init-method="init">
    
    <property name="g_connect_timeout" value="60"/>
    
    <property name="g_network_timeout" value="80"/>
    
    <property name="g_anti_steal_token" value="true"/>
    <property name="g_secret_key" value="FastDFS1234567890"/>
    <property name="poolConfig">
      <bean class="com.anniweiya.fastdfs.pool.PoolConfig">
        
        <property name="maxTotal" value="100"/>
        
        <property name="maxIdle" value="10"/>
      bean>
    property>
    
    <property name="tracker_servers" value="120.77.41.37:22122"/>
    
    <property name="g_tracker_http_port" value="8080"/>
    
    <property name="nginx_address" value="120.77.41.37:8888"/>
  bean>

  
  <bean id="fastDFSTemplate" class="com.anniweiya.fastdfs.FastDFSTemplate">
    <constructor-arg ref="fastDFSFactory"/>
  bean>

fastDFS自定义异常处理

/**
 * 
 * @Description: 文件上传异常 
 * @author: Aaron
 * @date: 2017年7月12日 下午6:56:09
 */
public class FastDFSException extends Exception {

    // serialVersionUID : TODO
	private static final long serialVersionUID = 1L;
	@SuppressWarnings("unused")
	
	//错误编码
	private int errorCode = 0;

    public FastDFSException(int errorCode) {
        this.errorCode = errorCode;
    }

    public FastDFSException(String message, int errorCode) {
        super(message);
        this.errorCode = errorCode;
    }

    public FastDFSException(String message, Throwable cause, int errorCode) {
        super(message, cause);
        this.errorCode = errorCode;
    }

    public FastDFSException(Throwable cause, int errorCode) {
        super(cause);
        this.errorCode = errorCode;
    }

    public FastDFSException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace,
                            int errorCode) {
        super(message, cause, enableSuppression, writableStackTrace);
        this.errorCode = errorCode;
    }
}

使用连接池创建连接

/**
 * 
 * @Description: 使用连接池创建连接 
 * @author: Aaron
 * @date: 2017年7月12日 下午6:57:05
 */
class ConnectionFactory extends BasePooledObjectFactory {
    private FastDFSTemplateFactory factory;

    public ConnectionFactory(FastDFSTemplateFactory templateFactory) {
        this.factory = templateFactory;
    }

    @Override
    public StorageClient create() throws Exception {
        TrackerClient trackerClient = new TrackerClient(factory.getG_tracker_group());
        TrackerServer trackerServer = trackerClient.getConnection();
        return new StorageClient(trackerServer, null);
    }

    @Override
    public PooledObject wrap(StorageClient storageClient) {
        return new DefaultPooledObject<>(storageClient);
    }

    public PooledObject makeObject() throws Exception {
        return wrap(create());
    }

    public void destroyObject(StorageClient obj) throws Exception {
        close(obj.getTrackerServer());
    }

    private void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException ignored) {
            }
        }
    }
}

连接池工厂

/**
 * 
 * @Description: 连接池工厂
 * @author: Aaron
 * @date: 2017年7月12日 下午6:58:09
 */
public class ConnectionPoolFactory {

	
    private GenericObjectPool pool;


    public ConnectionPoolFactory(FastDFSTemplateFactory fastDFSTemplateFactory) {
        pool = new GenericObjectPool<>(new ConnectionFactory(fastDFSTemplateFactory));
    }

    public StorageClient getClient() throws Exception {
        return pool.borrowObject();
    }
    
    public void releaseConnection(StorageClient client) {
        try {
            pool.returnObject(client);
        } catch (Exception ignored) {
        }
    }

    /**
     * 
     * @Description: 修改属性
     * @param poolConfig
     * @author: Aaron
     * @date: 2017年7月12日 下午6:59:02
     */
    @SuppressWarnings("unused")
	private void toConfig(PoolConfig poolConfig) {
        pool.setMaxTotal(poolConfig.maxTotal);
        pool.setMaxIdle(poolConfig.maxIdle);
        pool.setMinIdle(poolConfig.minIdle);
        pool.setTestOnBorrow(poolConfig.testOnBorrow);
        pool.setMaxWaitMillis(poolConfig.maxWait);
    }

}

连接池配置类

/**
 * 
 * @Description: 连接池配置
 * @author: Aaron
 * @date: 2017年7月12日 下午7:00:07
 */
public class PoolConfig {
    public int maxIdle = 10;
    public int minIdle = 0;
    public int maxTotal = 10;
    public long maxWait = -1L;
    public boolean testOnBorrow = false;


    public byte whenExhaustedAction = 1;
    public boolean testOnReturn = false;
    public boolean testWhileIdle = false;
    public long timeBetweenEvictionRunsMillis = -1L;
    public int numTestsPerEvictionRun = 3;
    public long minEvictableIdleTimeMillis = 1800000L;
    public long softMinEvictableIdleTimeMillis = -1L;
    public boolean lifo = true;

    public PoolConfig() {
    }

    public int getMaxIdle() {
        return maxIdle;
    }

    public void setMaxIdle(int maxIdle) {
        this.maxIdle = maxIdle;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public int getMaxTotal() {
        return maxTotal;
    }

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public byte getWhenExhaustedAction() {
        return whenExhaustedAction;
    }

    public void setWhenExhaustedAction(byte whenExhaustedAction) {
        this.whenExhaustedAction = whenExhaustedAction;
    }

    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public boolean isTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public boolean isTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public int getNumTestsPerEvictionRun() {
        return numTestsPerEvictionRun;
    }

    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
    }

    public long getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }

    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    public long getSoftMinEvictableIdleTimeMillis() {
        return softMinEvictableIdleTimeMillis;
    }

    public void setSoftMinEvictableIdleTimeMillis(long softMinEvictableIdleTimeMillis) {
        this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis;
    }

    public boolean isLifo() {
        return lifo;
    }

    public void setLifo(boolean lifo) {
        this.lifo = lifo;
    }
}

文件信息描述

/**
 * 
 * @Description: 文件信息描述
 * @author: Aaron
 * @date: 2017年7月12日 下午7:00:32
 */
public class FastDfsInfo implements java.io.Serializable {

    // serialVersionUID : TODO
	private static final long serialVersionUID = 4858945733404165431L;
	private String group;
    private String path;
    private String fileAbsolutePath;

    public FastDfsInfo(String group, String path) {
        this.group = group;
        this.path = path;
    }

    @Override
    public String toString() {
        return "FastDfsInfo{" + "group='" + group + '\'' +
               ", path='" + path + '\'' +
               '}';
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getFileAbsolutePath() {
        return fileAbsolutePath;
    }

    public void setFileAbsolutePath(String fileAbsolutePath) {
        this.fileAbsolutePath = fileAbsolutePath;
    }

}


FastDFS 初始化工厂

/**
 * 
 * @Description: FastDFS 初始化
 * @author: Aaron
 * @date: 2017年7月12日 下午7:04:21
 */
public class FastDFSTemplateFactory {

	//连接超时时间
    private int g_connect_timeout;
    //网络超时时间
    private int g_network_timeout;
    //编码
    private String g_charset;
    //tracker 端口
    private int g_tracker_http_port;
    //防盗链token是否需要
    private boolean g_anti_steal_token;
    //FastDFS key
    private String g_secret_key;
    //tracker 地址
    private List tracker_servers;
    //nginx 地址
    private List nginx_address;
    
    private TrackerGroup g_tracker_group;

    private PoolConfig poolConfig = new PoolConfig();


    private String protocol = "http://";
    private String sepapator = "/";


    public void init() throws Exception {

        if (g_connect_timeout <= 0) {
            g_connect_timeout = ClientGlobal.DEFAULT_CONNECT_TIMEOUT;
        }

        if (g_network_timeout <= 0) {
            g_network_timeout = ClientGlobal.DEFAULT_NETWORK_TIMEOUT;
        }
        g_connect_timeout *= 1000; //millisecond
        g_network_timeout *= 1000; //millisecond

        if (g_charset == null || g_charset.length() == 0) {
            g_charset = "UTF-8";
        }

        if (g_tracker_http_port <= 0) {
            g_tracker_http_port = 80;
        }

        if (tracker_servers == null || tracker_servers.isEmpty()) {
            throw new FastDFSException("item \"tracker_server\"  not found", -1);
        }

        InetSocketAddress[] tracker_servers_socket = new InetSocketAddress[tracker_servers.size()];
        for (int i = 0; i < tracker_servers.size(); i++) {
            String str = tracker_servers.get(i);
            String[] parts = str.split("\\:", 2);
            if (parts.length != 2) {
                throw new FastDFSException(
                        "the value of item \"tracker_server\" is invalid, the correct format is host:port", -2);
            }

            tracker_servers_socket[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim()));
        }
        g_tracker_group = new TrackerGroup(tracker_servers_socket);

        if (g_anti_steal_token) {
            if (g_secret_key == null || "".equals(g_secret_key)) {
                throw new FastDFSException("item \"secret_key\"  not found", -2);
            }
        }
        setToGlobal();
    }

    private void setToGlobal() {
        ClientGlobal.setG_connect_timeout(this.g_connect_timeout);
        ClientGlobal.setG_network_timeout(this.g_network_timeout);
        ClientGlobal.setG_charset(this.g_charset);
        ClientGlobal.setG_tracker_http_port(this.g_tracker_http_port);
        ClientGlobal.setG_anti_steal_token(this.g_anti_steal_token);
        ClientGlobal.setG_secret_key(this.g_secret_key);
        ClientGlobal.setG_tracker_group(this.g_tracker_group);
    }

    public PoolConfig getPoolConfig() {
        if (poolConfig == null) {
            return new PoolConfig();
        }
        return poolConfig;
    }

    public void setPoolConfig(PoolConfig poolConfig) {
        this.poolConfig = poolConfig;
    }

    public int getG_connect_timeout() {
        return g_connect_timeout;
    }

    public void setG_connect_timeout(int g_connect_timeout) {
        this.g_connect_timeout = g_connect_timeout;
    }

    public int getG_network_timeout() {
        return g_network_timeout;
    }

    public void setG_network_timeout(int g_network_timeout) {
        this.g_network_timeout = g_network_timeout;
    }

    public String getG_charset() {
        return g_charset;
    }

    public void setG_charset(String g_charset) {
        this.g_charset = g_charset;
    }

    public int getG_tracker_http_port() {
        return g_tracker_http_port;
    }

    public void setG_tracker_http_port(int g_tracker_http_port) {
        this.g_tracker_http_port = g_tracker_http_port;
    }

    public boolean isG_anti_steal_token() {
        return g_anti_steal_token;
    }

    public void setG_anti_steal_token(boolean g_anti_steal_token) {
        this.g_anti_steal_token = g_anti_steal_token;
    }

    public String getG_secret_key() {
        return g_secret_key;
    }

    public void setG_secret_key(String g_secret_key) {
        this.g_secret_key = g_secret_key;
    }

    public List getTracker_servers() {
        return tracker_servers;
    }

    public void setTracker_servers(String tracker_servers) {
        this.tracker_servers = Arrays.asList(tracker_servers.split(","));
    }

    public List getNginx_address() {
        return nginx_address;
    }

    public void setNginx_address(String nginx_address) {
        this.nginx_address = Arrays.asList(nginx_address.split(","));
    }

    public TrackerGroup getG_tracker_group() {
        return g_tracker_group;
    }

    public void setG_tracker_group(TrackerGroup g_tracker_group) {
        this.g_tracker_group = g_tracker_group;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getSepapator() {
        return sepapator;
    }

    public void setSepapator(String sepapator) {
        this.sepapator = sepapator;
    }
}


**FastDFS 模板类 **

/**
 * 
 * @Description: FastDFS 模板类 
 * @author: Aaron
 * @date: 2017年7月12日 下午7:01:03
 */
public class FastDFSTemplate {

    private ConnectionPoolFactory connPoolFactory;
    private FastDFSTemplateFactory factory;

    public FastDFSTemplate(FastDFSTemplateFactory factory) {
        this.connPoolFactory = new ConnectionPoolFactory(factory);
        this.factory = factory;
    }

   /**
    * 
    * @Description: 上传文件
    * @param data
    * @param ext 后缀,如:jpg、bmp(注意不带.)
    * @return
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:01:32
    */
    public FastDfsInfo upload(byte[] data, String ext) throws FastDFSException {
        return this.upload(data, ext, null);
    }

   
   /**
    * 
    * @Description: 上传文件
    * @param data
    * @param ext 后缀,如:jpg、bmp(注意不带.)
    * @param values
    * @return
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:01:55
    */
    public FastDfsInfo upload(byte[] data, String ext, Map values) throws FastDFSException {
        NameValuePair[] valuePairs = null;
        if (values != null && !values.isEmpty()) {
            valuePairs = new NameValuePair[values.size()];
            int index = 0;
            for (Map.Entry entry : values.entrySet()) {
                valuePairs[index] = new NameValuePair(entry.getKey(), entry.getValue());
                index++;
            }
        }
        StorageClient client = getClient();

        try {
            String[] uploadResults = client.upload_file(data, ext, valuePairs);
            String groupName = uploadResults[0];
            String remoteFileName = uploadResults[1];
            FastDfsInfo fastDfsInfo = new FastDfsInfo(groupName, remoteFileName);
            if (factory != null) {
                this.setFileAbsolutePath(fastDfsInfo);
            }
            return fastDfsInfo;
        } catch (Exception e) {
            throw new FastDFSException(e.getMessage(), e, 0);
        } finally {
            releaseClient(client);
        }
    }

   
   /**
    * 
    * @Description: 下载文件
    * @param dfs
    * @return
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:02:27
    */
    public byte[] loadFile(FastDfsInfo dfs) throws FastDFSException {
        return this.loadFile(dfs.getGroup(), dfs.getPath());
    }

   
   /**
    * 
    * @Description: 下载文件
    * @param groupName
    * @param remoteFileName
    * @return
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:02:46
    */
    public byte[] loadFile(String groupName, String remoteFileName) throws FastDFSException {
        StorageClient client = getClient();
        try {
            return client.download_file(groupName, remoteFileName);
        } catch (Exception e) {
            throw new FastDFSException(e.getMessage(), e, 0);
        } finally {
            releaseClient(client);
        }
    }

   
   /**
    * 
    * @Description: 删除文件
    * @param dfs
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:02:59
    */
    public void deleteFile(FastDfsInfo dfs) throws FastDFSException {
        this.deleteFile(dfs.getGroup(), dfs.getPath());
    }

   /**
    * 
    * @Description: 删除文件
    * @param groupName
    * @param remoteFileName
    * @throws FastDFSException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:03:13
    */
    public void deleteFile(String groupName, String remoteFileName) throws FastDFSException {
        int code;
        StorageClient client = getClient();
        try {
            code = client.delete_file(groupName, remoteFileName);
        } catch (Exception e) {
            throw new FastDFSException(e.getMessage(), e, 0);
        } finally {
            releaseClient(client);
        }
        if (code != 0) {
            throw new FastDFSException(code);
        }
    }

    
   /**
    * 
    * @Description: 设置远程可访问路径
    * @param group
    * @param path
    * @return
    * @throws IOException
    * @throws NoSuchAlgorithmException
    * @throws MyException
    * @author: Aaron
    * @date: 2017年7月12日 下午7:03:34
    */
    public String setFileAbsolutePath(String group, String path)
            throws IOException, NoSuchAlgorithmException, MyException {
        int ts = (int) (System.currentTimeMillis() / 1000), port;
        String token = "";
        if (factory.isG_anti_steal_token()) {
            token = ProtoCommon.getToken(path, ts, factory.getG_secret_key());
            token = "?token=" + token + "&ts=" + ts;
        }
        List addressList;
        if (factory.getNginx_address() != null) {
            addressList = factory.getNginx_address();
        } else {
            addressList = factory.getTracker_servers();
        }

        Random random = new Random();
        int i = random.nextInt(addressList.size());
        String[] split = addressList.get(i).split(":", 2);

        if (split.length > 1) {
            port = Integer.parseInt(split[1].trim());
        } else {
            port = factory.getG_tracker_http_port();
        }
        String address = split[0].trim();
        return factory.getProtocol() +
               address + ":" +
               port +
               factory.getSepapator() +
               group +
               factory.getSepapator() +
               path + token;

    }

    public void setFileAbsolutePath(FastDfsInfo fastDfsInfo) throws IOException, NoSuchAlgorithmException, MyException {
        fastDfsInfo.setFileAbsolutePath(this.setFileAbsolutePath(fastDfsInfo.getGroup(), fastDfsInfo.getPath()));
    }

    protected StorageClient getClient() {
        StorageClient client = null;
        while (client == null) {
            try {
                client = connPoolFactory.getClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return client;
    }

    protected void releaseClient(StorageClient client) {
        connPoolFactory.releaseConnection(client);
    }

}


测试类

/**
 * 
 * @Description: 测试连接 
 * @author: Aaron
 * @date: 2017年7月12日 下午7:08:59
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-fastdfs.xml")
public class MainTest {

    @Resource
    private FastDFSTemplate dfsTemplate;

    @Test
    public void testUploadAndDel() throws FastDFSException {
        FastDfsInfo rv = dfsTemplate.upload("".getBytes(), "txt");
        System.out.println(rv);
        dfsTemplate.deleteFile(rv);
    }

    @Test
    public void testPool() throws InterruptedException {
        Runnable runnable = () -> {
            try {
                File file = new File("/Users/duhuifan/Downloads/edu-demo-fdfs/TestFile/aaron.jpg");
                FileInputStream fis = new FileInputStream(file);
                byte[] b = new byte[fis.available()];
                fis.read(b);
                Map map = new HashMap<>();
                FastDfsInfo rv = dfsTemplate.upload(b, "jpg", map);
                System.out.println(rv.getFileAbsolutePath());
                //dfsTemplate.deleteFile(rv);
            } catch (Exception e) {
                e.printStackTrace();
            }
        };

        for (int i = 0; i < 1; i++) {
            new Thread(runnable).start();
        }
        Thread.currentThread().join();
    }

}


GitHub项目源码

https://github.com/Aaron258/fastdfs-common.git

你可能感兴趣的:(项目工具)