当前位置:   article > 正文

FastDFS分布式文件系统详解

fastdfs

FastDFS 简介

FastDFS 是基于 C 语言开发的,是一个轻量级开源的高性能分布式文件系统。主要功能有:文件存储、文件同步、文件访问(文件上传/下载),解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。FastDFS 特别适合中大型网站以文件为载体的在线服务,适合存储 4KB ~ 500MB 之间的小文件,如照片共享网站、视频共享网站(图片、文档、音频、视频等等)。
Github地址

FastDFS 架构

在这里插入图片描述
Client
客户端,实现文件上传下载的服务器,就是我们自己的项目所部署在的服务器。通过专有接口,使用 TCP/IP 协议与跟踪服务器或存储服务器进行数据交互。FastDFS 向使用者提供基本文件访问接口,比如 upload、download、append、delete等,以客户端库的方式提供给用户使用。

Tracker Server
跟踪服务器,负责文件访问的调度和负载均衡,负责管理所有的 Storage Server 和 group 组/卷。

Storage Server
存储服务器,负责文件存储,文件同步/备份,提供文件访问接口,文件元数据管理。以 group 为单位,每个 group 内可以有多台 Storage Server,数据互为备份,达到容灾的目的。每个 Storage 在启动以后会主动连接 Tracker,告知自己所属 group 等存储相关信息,并保持周期性心跳。

Group
 组,也可称为 Volume 卷。同组内服务器上的文件是完全相的,同一组内的 Storage Server 之间是对等的,文件上传、删除等操作可以在任意一台 Storage Server 上进行。

Metadata
文件系统中存储的数据分为数据元数据两部分,数据是指文件中的实际数据,即文件的实际内容;而元数据是用来描述一个文件特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息等等。如果文件是一张图片,元数据就是图片的宽,高等等。

FastDFS 存储策略

为了支持大容量存储,Storage 存储服务器采用了分组(或分卷)的方式。存储系统由一个或多个组组成,组与组之间的文件是相互独立的,所有组的文件容量累加就是整个存储系统中的文件容量。一个组可以由一台或多台存储服务器组成,一个组下的存储服务器中的文件都是相同的,组中的多台存储服务器起到了冗余备份和负载均衡的作用。
  当组中增加了新的服务器时,系统会自动同步已有的文件,同步完成后,系统自动将新增的服务器切换至线上提供服务。
  当存储空间不足时,可以动态添加组,只需要增加一台或多台服务器,并将它们配置为一个新的组,即可扩大存储系统的容量。当你的某个应用或者模块(对应的 group)的并发过高的时候,可以直接在 group 中增加若干个 Storage 来实现负载均衡。
  为了避免单个目录下的文件数太多,当 Storage 第一次启动时,会在每个数据存储目录中创建 2 级子目录,每级 256 个,总共 65536 个目录,上传的文件会以 hash 的方式被路由到其中某个目录下,然后将文件数据直接作为一个本地文件存储到该目录。

FastDFS 安装

首先要说明一下: tracker 和 storage 其实都是 fastdfs ,只不过启动时通过不同的配置文件启动,所扮演的角色不同而已。也就是说,安装 tracker 和 storage 就是在安装 fastdfs ,然后通过每个角色具体的配置文件启动即可。

下载资源

直接通过 Github:https://github.com/happyfish100 下载 libfastcommon , fastdfs ,fastdfs-nginx-module 三个项目对应的压缩包或者使用 git 命令下载,或者通过资源地址:https://sourceforge.net/projects/fastdfs/files/ 下载。

  • libfastcommon :从 fastdfs 项目和 fastdht 项目中提取出来的公共 C 函数库。
  • fastdfs :FastDFS 核心项目。
  • fastdfs-nginx-module :Nginx 整合 FastDFS 时 Nginx 需要添加的模块资源。

安装依赖

FastDFS 是基于 C 语言开发的,安装它之前必须先安装它所依赖的环境。

yum install -y make cmake gcc gcc-c++
  • 1

安装公共函数库

上传资源 libfastcommon-master.zip 至服务器 /usr/local/src 目录后并解压。

#安装 unzip 用于解压
yum install -y unzip
#解压 libfastcommon 至当前所在目录
unzip libfastcommon-master.zip
# 进入解压后的 libfastcommon-master 目录
cd libfastcommon-master
# 编译并安装
./make.sh && ./make.sh install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

libfastcommon 默认安装在 /usr/lib64 和 /usr/include/fastcommon 两个目录中,并且会在 /usr/lib 目录中创建软链接。
在这里插入图片描述

安装 FastDFS

上传资源 fastdfs-master.zip 至服务器 /usr/local/src 目录后并解压。

#解压 fastdfs 至当前所在目录
unzip fastdfs-master.zip
# 进入解压后的 fastdfs-master 目录
cd fastdfs-master
# 编译并安装
./make.sh && ./make.sh install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

fastdfs 默认安装在以下位置:

  • /usr/bin :可执行文件
  • /etc/fdfs :配置文件
  • /etc/init.d :主程序代码
  • /usr/include/fastdfs :插件组
    在这里插入图片描述

启动 Tracker

tracker 和 storage 其实都是 fastdfs ,只不过启动时通过不同的配置文件启动,所扮演的角色不同而已。也就是说,安装 tracker 和 storage 就是在安装 fastdfs ,然后通过每个角色具体的配置文件启动即可。

查看 /etc/fdfs 目录下所有配置文件。

[root@localhost ~]# ls /etc/fdfs/
client.conf.sample storage.conf.sample storage_ids.conf.sample
tracker.conf.sample
  • 1
  • 2
  • 3

client.conf.sample :客户端的配置文件,测试用
storage.conf.sample :存储器的配置文件
tracker.conf.sample :跟踪器的配置文件

编辑 tracker.conf 配置文件

#拷贝文件 tracker.conf.sample 并重命名为 tracker.conf
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
#编辑 tracker.conf 配置文件
vi /etc/fdfs/tracker.conf
  • 1
  • 2
  • 3
  • 4

配置文件中的配置项还是蛮多的,这里暂且关注以下几个即可,后期根据实际情况再对其他配置项
作出调整

#允许访问 tracker 服务器的 IP 地址,为空则表示不受限制
bind_addr =
#tracker 服务监听端口
port = 22122
#tracker 服务器的运行数据和日志的存储父路径(需要提前创建好)
base_path = /fastdfs/tracker
#tracker 服务器 HTTP 协议下暴露的端口
http.server_port = 8080
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

启动 tracker 服务

#创建 tracker 服务器的运行数据和日志的存储父路径
mkdir -p /fastdfs/tracker
#启动 tracker 服务
service fdfs_trackerd start
#查看 tracker 服务状态
service fdfs_trackerd status
#重启 tracker 服务
service fdfs_trackerd restart
#停止 tracker 服务
service fdfs_trackerd stop
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

启动 Storage

编辑 storage.conf 配置文件

#拷贝文件 storage.conf.sample 并重命名为 storage.conf
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
#编辑 storage.conf 配置文件
vi /etc/fdfs/storage.conf
  • 1
  • 2
  • 3
  • 4

也是先暂时关注几个

#storage 组名/卷名,默认为 group1
group_name = group1
#允许访问 storage 服务器的 IP 地址,为空则表示不受限制
bind_addr =
#storage 服务器的运行数据和日志的存储父路径(需要提前创建好)
base_path = /fastdfs/storage/base
#storage 服务器中客户端上传的文件的存储父路径(需要提前创建好)
store_path0 = /fastdfs/storage/store
#storage 服务器 HTTP 协议下暴露的端口
http.server_port = 8888
#tracker 服务器的 IP 和端口
tracker_server = 192.168.10.101:22122
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

启动 storage 服务

#创建 storage 服务器的运行数据和日志的存储父路径
mkdir -p /fastdfs/storage/base
#创建 storage 服务器中客户端上传的文件的存储父路径
mkdir -p /fastdfs/storage/store
#启动 storage 服务
service fdfs_storaged start
#查看 storage 服务状态
service fdfs_storaged status
#重启 storage 服务
service fdfs_storaged restart
#停止 storage 服务
service fdfs_storaged stop
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

查看 /fastdfs/storage/store 目录可以看到 Storage 服务器创建了 65536 个文件夹用于存储客户端上传的文件。
 在这里插入图片描述

Client 操作

FastDFS 向使用者提供基本文件访问接口,比如 upload、download、append、delete 等,以客
户端库的方式提供给用户使用。

编辑 client.conf 配置文件

#拷贝文件 client.conf.sample 并重命名为 client.conf
cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
#编辑 client.conf 配置文件
vi /etc/fdfs/client.conf
  • 1
  • 2
  • 3
  • 4

修改配置文件中以下两处内容即可

#client 客户端的运行数据和日志的存储父路径(需要提前创建好)
base_path = /fastdfs/client
#tracker 服务器的 IP 和端口
tracker_server = 192.168.10.101:22122
  • 1
  • 2
  • 3
  • 4

记得 mkdir -p /fastdfs/client 创建 Client 目录

上传文件

在这里插入图片描述
选择 Tracker Server
如上图所示,Storage Server 会定期向 Tracker Server 发送自己的所属 group 等存储相关信息。如果 Tracker Server 是集群环境,因为各个 Tracker 之间的关系是对等的,所以客户端上传时可以选择任意一个 Tracker

选择 group
当 Tracker 收到客户端上传文件的请求时,会为该文件分配一个可用的 group 用于存储,当选定了group 以后就要决定给客户端分配 group 中的哪个 Storage Server
在这里插入图片描述
 如上图所示, tracker.conf 配置文件中 group 的可选规则有:

  • round robin :所有的 group 间轮询
  • specify group :指定一个具体的 group
  • load balance :优先选择剩余存储空间多的 group

选择 Storage Server
当分配好 Storage Server 以后,客户端会向 Storage Server 发送上传文件请求,Storage Server会为文件分配一个具体的数据存储目录
在这里插入图片描述
storage.conf 配置文件中文件分发的可选规则有:

  • round robin :在 group 中的所有 Storage 间轮询
  • random :随机,按 hash code 分发

生成 file_id
 选定存储目录以后,Storage 会为文件生一个 file_id,由 Storage Server IP、文件创建时间、文件
大小、文件 crc32 和一个随机数组成,然后将这个二进制串进行 base64 编码,转换为字符串

生成文件名
当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由 group名称/存储目录/两级子目录/file_id.后缀名 拼接而成
在这里插入图片描述
FastDFS 文件上传返回信息解读

  • group1 :组名/卷名。文件上传成功以后所在的 Storage 组名称,由 Storage 服务器返回
  • M00 :虚拟磁盘路径。与 Storage 配置文件中磁盘选项 store_path* 对应。如果配置了store_path0 则是M00 ,如果配置了 store_path1 则是 M01 ,以此类推。比如:store_path0 =
    /fastdfs/storage/store ,M00 则表示: /fastdfs/storage/store/data
  • /02/44 :数据两级目录。Storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据 文件
  • wKgDrE34E8wAAAAAAAAGkEIYJK42378 :file_id,由 Storage Server IP、文件创建时间、文件大小、文件 crc32 和一个随机数组成,然后将这个二进制串进行 base64 编码,转换为字符串

上传方式一

上传命令格式为: fdfs_upload_file /etc/fdfs/client.conf 要上传的文件

[root@localhost ~]# fdfs_upload_file /etc/fdfs/client.conf
/usr/local/src/china.jpg
group1/M00/00/00/wKgKZl9skn6AHZKUAADhaCZ_RF0650.jpg
  • 1
  • 2
  • 3

在这里插入图片描述
文件上传成功以后,会返回该文件在 Storage 服务器中的存储位置及随机生成的文件名。其中group1 表示 Storage 组名/卷名, M00 是一个虚拟目录,表示 /fastdfs/storage/store/data/ 真实路径中的 data 目录

查看 Storage 服务器发现该文件已成功上传
在这里插入图片描述

上传方式二

或者使用: fdfs_test /etc/fdfs/client.conf upload 要上传的文件 ,会返回该文件上传成功以后详细的相关信息
在这里插入图片描述

  • group_name :Storage 组名/卷名
  • remote_filename :上传成功文件的存储路径及文件名
  • source_ip address :上传成功文件所在的 Storage 服务器的 IP 地址
  • file timestamp :上传成功文件时的时间戳
  • file size :上传成功文件的文件大小
  • example file url :上传成功文件的 url 地址,配合 Nginx 可以直接访问
  • storage_upload_slave_by_filename :FastDFS 的文件主/从特性,由主文件产生从文件

如下图所示,查看 Storage 服务器发现该文件已成功上传。后缀为 jpg-m 的文件存放了上传成功文件的元数据信息
在这里插入图片描述

下载文件

在这里插入图片描述
  客户端 upload file 成功以后,会拿到一个 Storage 生成的文件名,接下来客户端根据这个文件名即可访问到该文件。跟 upload file 一样,在 download file 时客户端可以选择任意 Tracker Server。客户端发送 download 请求给某个 Tracker,必须带上文件名信息,Tracke 从文件名中解析出该文件的
group、大小、创建时间等信息,然后为该请求选择一个 Storage 用于提供读取服务

下载方式一

下载命令格式为: fdfs_download_file /etc/fdfs/client.conf group_name/remote_filename

fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgKZl9smBAVBRKAADhaCZ_RF0518.jpg
  • 1

下载方式二

使用: fdfs_test /etc/fdfs/client.conf download group_name remote_filename

fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/wKgKZl9smBAVBRKAADhaCZ_RF0518.jpg
  • 1

删除文件

删除方式一

删除命令格式为: fdfs_delete_file /etc/fdfs/client.conf 要删除的文件

fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/wKgKZl9smBAVBRKAADhaCZ_RF0518.jpg
  • 1

Tips:删除文件操作会将元数据文件一并删除

删除方式二

使用: fdfs_test /etc/fdfs/client.conf delete group_name remote_filename

fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/wKgKZl9smBAVBRKAADhaCZ_RF0518_big.jpg
  • 1

使用nginx通过 HTTP 访问 FastDFS 中保存的图片信息

Nginx 整合 FastDFS 时 Nginx 需要添加 fastdfs-nginx-module 模块

直接通过 Github:https://github.com/happyfish100/fastdfs-nginx-modul 下载压缩包或者使用 git 命令下载
或者通过资源地址:**https://sourceforge.net/projects/fastdfs/files/** 下载。
  • 1
  • 2

下载以后,上传资源 fastdfs-nginx-module-master.zip 至服务器 /usr/local/src 目录后并解压。

unzip fastdfs-nginx-module-master.zip
  • 1

复制配置文件 mod_fastdfs.conf 到 /etc/fdfs 目录中

cp /usr/local/src/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
  • 1

vim /etc/fdfs/mod_fastdfs.conf 编辑配置文件,主要关注以下部分

#tracker 服务器的 IP 和端口
tracker_server = 192.168.10.101:22122
#url 地址是否包含组名/卷名
url_have_group_name = true
#数据组/卷对应的路径地址
store_path0 = /fastdfs/storage/store
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

复制 fastdfs 安装包中的两个配置文件 http.conf 和 mime.types 到 /etc/fdfs 目录中

cp /usr/local/src/fastdfs-master/conf/http.conf /etc/fdfs/
cp /usr/local/src/fastdfs-master/conf/mime.types /etc/fdfs/
  • 1
  • 2

安装 Nginx

#下载 nginx 压缩包
wget -P /usr/local/src http://nginx.org/download/nginx-1.18.0.tar.gz
#解压
tar -zxvf /usr/local/src/nginx-1.18.0.tar.gz -C /usr/local/src
  • 1
  • 2
  • 3
  • 4

安装依赖

Nginx 是基于 C 语言开发的,HTTP 模块使用了 pcre 来解析正则表达式,且可以使用 zlib 对 HTTP
包的内容进行 gzip 压缩,Nginx 不仅支持 HTTP 协议,还支持 HTTPS,HTTPS 需要 openssl 提供支
持,所以安装 Nginx 之前必须先安装它所依赖的环境

yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl-devel
  • 1

安装 Nginx

#切换至 nginx 的解压目录
cd /usr/local/src/nginx-1.18.0
#创建 nginx 的安装目录
mkdir -p /usr/local/nginx
#添加 fastdfs-nginx-module 模块,指定 nginx 的安装路径
./configure --add-module=/usr/local/src/fastdfs-nginx-module-master/src --
prefix=/usr/local/nginx/
#编译并安装
make && make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

配置 Nignx

vim /usr/local/nginx/conf/nginx.conf 编辑配置文件,在 80 端口下添加以下内容。关于Nginx 启动用户的问题请根据自身实际环境进行配置

在这里插入图片描述

测试

启动 Nginx,命令为: /usr/local/nginx/sbin/nginx
客户端上传图片以后得到文件名为:group1/M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg

在浏览器上访问
在这里插入图片描述

其实目前的环境只是一个单节点的 FastDFS,如果要实现高可用, Tracker 和 Storage 都需要搭建多个节点形成集群环境才行

Java客户端操作FastDFS实现文件上传下载替换删除

FastDFS 的作者余庆先生已经为我们开发好了 Java 对应的 SDK。这里需要解释一下:作者余庆并没有及时更新最新的 Java SDK 至 Maven 中央仓库,目前中央仓库最新版仍旧是 1.27 版。所以我们需要通过 Github:https://github.com/happyfish100/fastdfs-client-java 下载项目源码,再通过命令 mvn clean install 编译打包导入 Maven 本地仓库使用
在这里插入图片描述

创建项目

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

添加依赖

在项目的 pom.xml 中添加以下依赖。因为我们需要一些常用工具包和单元测试,所以需要引入它们

<!-- fastdfs java client -->
<dependency>
	<groupId>org.csource</groupId>
	<artifactId>fastdfs-client-java</artifactId>
	<version>1.29-SNAPSHOT</version>
</dependency>
<!-- apache commons lang3 工具包 -->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-lang3</artifactId>
	<version>3.11</version>
</dependency>
<!-- junit 单元测试 -->
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.13</version>
	<scope>test</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

编写配置文件

fdfs_client.conf

# 超时时间
connect_timeout = 10
network_timeout = 30
# 编码字符集
charset = UTF-8
# tracker 服务器 HTTP 协议下暴露的端口
http.tracker_http_port = 8080
# tracker 服务器的 IP 和端口
tracker_server = 192.168.10.101:22122
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

工具类

package org.example.client;
import org.apache.commons.lang3.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.*;
/**
* FastDFS 分布式文件系统 Java 客户端工具类
* 具体功能:文件上传、下载、替换、删除、查询文件元数据、查看文件详情
*/
public class FastDFSClient {
// 获取配置文件地址
	private static final String CONF_FILENAME = Thread.currentThread()
		.getContextClassLoader().getResource("").getPath() + "fdfs_client.conf";
	// Storage 存储服务器客户端
	private static StorageClient storageClient = null;
	static {
		try {
		// 加载配置文件
		ClientGlobal.init(CONF_FILENAME);
		// 初始化 Tracker 客户端
		TrackerClient trackerClient = new
		TrackerClient(ClientGlobal.g_tracker_group);
		// 初始化 Tracker 服务端
		TrackerServer trackerServer = trackerClient.getTrackerServer();
		// 初始化 Storage 服务端
		StorageServer storageServer =
		trackerClient.getStoreStorage(trackerServer);
		// 初始化 Storage 客户端
		storageClient = new StorageClient(trackerServer, storageServer);
	} catch (IOException e) {
		e.printStackTrace();
	} catch (MyException e) {
		e.printStackTrace();
	}
}
	/**
	* 文件上传
	*
	* @param inputStream 上传的文件的字节输入流
	* @param fileName 上传的文件的原始名
	* @return
	*/
	public static String[] uploadFile(InputStream inputStream, String fileName){
		try {
			// 准备字节数组
			byte[] fileBuff = null;
			// 文件元数据
			NameValuePair[] metaList = null;
			if (inputStream != null) {
				// 查看文件的长度
				int len = inputStream.available();
				// 初始化元数据数组
				metaList = new NameValuePair[2];
				// 第一组元数据,文件的原始名称
				metaList[0] = new NameValuePair("file_name", fileName);
				// 第二组元数据,文件的长度
				metaList[1] = new NameValuePair("file_length",String.valueOf(len));
				// 创建对应长度的字节数组
				fileBuff = new byte[len];
				// 将输入流中的字节内容,读到字节数组中
				inputStream.read(fileBuff);
			}
			/*
			上传文件。
			参数含义:要上传的文件的内容(使用字节数组传递),上传的文件的类型(扩展名),
			元数据
			*/
			String[] fileids = storageClient.upload_file(fileBuff,getFileExt(fileName), metaList);
			return fileids;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (MyException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	* 文件上传
	*
	* @param file 上传的文件
	* @param fileName 上传的文件的原始名
	* @return
	*/
	public static String[] uploadFile(File file, String fileName) {
		try (FileInputStream fis = new FileInputStream(file)) {
			return uploadFile(fis, fileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	* 获取文件后缀名(不带点)
	*
	* @param fileName
	* @return 如:"jpg" or ""
	*/
	private static String getFileExt(String fileName) {
		if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
			return "";
		}
		return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
	}

	/**
	* 获取文件详情
	*
	* @param groupName 组/卷名,默认值:group1
	* @param remoteFileName 文件名,例
	如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
	* @return 文件详情
	*/
	public static FileInfo getFileInfo(String groupName, String remoteFileName){
		try {
			return storageClient.get_file_info(groupName == null ? "group1" :groupName, remoteFileName);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (MyException e) {
			e.printStackTrace();
		}
			return null;
		}

	/**
	* 获取元数据
	*
	* @param groupName 组/卷名,默认值:group1
	* @param remoteFileName 文件名,例
	如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
	* @return 文件的元数据数组
	*/
	public static NameValuePair[] getMetaData(String groupName, StringremoteFileName) {
		try {
			// 根据组名和文件名通过 Storage 客户端获取文件的元数据数组
			return storageClient.get_metadata(groupName == null ? "group1" :groupName, remoteFileName);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (MyException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	* 文件下载
	*
	* @param groupName 组/卷名,默认值:group1
	* @param remoteFileName 文件名,例
	如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
	* @return 文件的字节输入流
	*/
	public static InputStream downloadFile(String groupName, StringremoteFileName) {
		try {
		// 根据组名和文件名通过 Storage 客户端获取文件的字节数组
		byte[] bytes = storageClient.download_file(groupName == null ? "group1" : groupName, remoteFileName);
		// 返回字节流对象
		InputStream inputStream = new ByteArrayInputStream(bytes);
		return inputStream;
	} catch (IOException e) {
		e.printStackTrace();
	} catch (MyException e) {
		e.printStackTrace();
	}
		return null;
	}

	/**
	* 文件删除
	*
	* @param groupName 组/卷名,默认值:group1
	* @param remoteFileName 文件名,例
	如:"M00/00/00/wKgKZl9tkTCAJAanAADhaCZ_RF0495.jpg"
	* @return 0为成功,非0为失败
	*/
	public static int deleteFile(String groupName, String remoteFileName) {
		int result = -1;
		try {
			// 根据组名和文件名通过 Storage 客户端删除文件
			result = storageClient.delete_file(groupName == null ? "group1" :groupName, remoteFileName);
	} catch (IOException e) {
		e.printStackTrace();
	} catch (MyException e) {
		e.printStackTrace();
	}
		return result;
	}

	/**
	* 修改一个已经存在的文件
	*
	* @param oldGroupName 旧组名
	* @param oldFileName 旧文件名
	* @param file 新文件
	* @param fileName 新文件名
	* @return
	*/
	public static String[] modifyFile(String oldGroupName, String oldFileName,File file, String fileName) {
		// 先上传
		String[] fileids = uploadFile(file, fileName);
		if (fileids == null) {
			return null;
		}
		// 再删除
		int delResult = deleteFile(oldGroupName, oldFileName);
		if (delResult != 0) {
		return null;
		}
		return fileids;
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216

测试

文件上传
// 文件上传
@Test
public void testUploadFile() {
	String[] fileids = FastDFSClient.uploadFile(new File("D:/china.jpg"),"china.jpg");
	for (String fileid : fileids) {
		System.out.println("fileid = " + fileid);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出

fileid = group1
fileid = M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg
  • 1
  • 2

在这里插入图片描述

文件详情
// 查看文件详情
@Test
public void testGetFileInfo() {
	FileInfo fileInfo = 	FastDFSClient.getFileInfo("group1","M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg");
	System.out.println("fileInfo = " + fileInfo);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
fileInfo = fetch_from_server = false, file_type = 1, source_ip_addr =192.168.10.102, file_size = 57704, create_timestamp = 2020-09-28 08:44:08, crc32= 645874781
  • 1
文件元数据
// 获取文件数据
@Test
public void testGetMetaData() {
	NameValuePair[] metaDatas = FastDFSClient.getMetaData("group1","M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg");
	for (NameValuePair metaData : metaDatas) {
	System.out.println(metaData.getName() + "---" + metaData.getValue());
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
file_length---57704
file_name---china.jpg
  • 1
  • 2
文件下载
// 文件下载
@Test
public void testDownloadFile() {
	InputStream is = FastDFSClient.downloadFile("group1","M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg");
	try (FileOutputStream fos = newFileOutputStream("D:/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg")) {
		int len = 0;
		byte[] bytes = new byte[1024];
		while ((len = is.read(bytes)) != -1) {
		fos.write(bytes, 0, len);
		fos.flush();
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
文件删除
// 文件删除
@Test
public void testDeleteFile() {
	int result = FastDFSClient.deleteFile("group1","M00/00/00/wKgKZl9xMdiAcOLdAADhaCZ_RF0096.jpg");
	System.out.println("result = " + result);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
result = 0
  • 1
文件替换
// 文件替换
@Test
public void testModifyFile() {
	String[] fileids = FastDFSClient.modifyFile("group1","M00/00/00/wKgKZl9xOS2ASdu8AADhaCZ_RF0898.jpg",new File("D:/mhw.jpg"),"mhw.jpg");
	for (String fileid : fileids) {
		System.out.println("fileid = " + fileid);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
fileid = group1
fileid = M00/00/00/wKgKZl9xOeaAFO00AACmo7QBGtA298.jpg
  • 1
  • 2

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/169952
推荐阅读
相关标签
  

闽ICP备14008679号