1、FastDFS

1.1、了解基础概念

1.1.1、什么是分布式文件系统?

  • 全称:Distributed File System,即简称的DFS
  • 这个东西可以是一个软件,也可以说是服务器,和tomcat差不多,即相当于软件也相当于是服务器,这个软件就是用来管理文件的
  • 这个软件所管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上
  • 服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件系统来管理这些服务器上的文件

1.1.2、传统文件系统 和 分布式文件系统对比

传统文件系统

  • 缺点

    • 所有的文件都存放在一台计算机中,如果这台计算机挂彩了,那么就会导致整个服务不可用( 文件不能上传和下载了 )
    • 如果这台计算机磁盘损坏了,那么会丢失所有的文件
    • 这台计算机的磁盘空间非常有限,很容易到达磁盘的上限,导致无法上传文件
  • 回顾玩servlet时的文件上传和下载

    文件上传

    • 假如前端轰HTML写法是如下的样子:
    		  <div id="image">
    <label for="">标题图片:</label>
    <input type="file" id="file" name="file" >
    <img src="" alt="" width="100px" height="150px">
    </div>
    • JS写法如下:
    		// 当图片发生改变时 —— 也就是用户点击file框,上传文件时
    $("#file").on( 'change' , function () { // 创建一个FormData空对象,就相当于是伪造了一个form表单
    let formData = new FormData(); // 这个FromData对象就用来装文件内容
    // 文件的files属性本质是个数组
    let files = $("#file").prop("files");
    formData.append("upFile" , files[0] ); $.ajax( { url: '/ajax/upload.do',
    type: 'post',
    data: formData,
    dataType: 'json', cache: false, // 上传文件不需要缓存
    contentType: false, // 不需要对内容类型进行处理 因为内容是一个FormData对象
    processData: false, // 不需要对数据进行处理,因为上面的data是一个FormData对象 // 后台返回的格式 :
    // { "errno":"0" , "data":[ {"alt":"1633528500498.jpg" , "url":"/upload/2021-10-06/1633528500498.jpg"} ] }
    success: function (info) {
    info.data.forEach( function (data) { // $("#image img").remove();
    // $("#image").append( ' <img src=" '+data.url+' " alt="" width="100px" height="150px"> ' ) /*
    注掉的这种是:html中没有img标签时使用
    因为:使用下面这种方法的情景是 —— 页面本来就有一个img框( 即:初始页面上这个file本身有一张图片 ),所以下面这种可以做到图片改变时把图片的路径换掉,也就是图片渲染( 也是数据回填 的思想 )
    但是:如果页面一开始file的位置是不应该有图片的,是后面用户选了之后才出现图片预览效果,那么:就使用注释掉的这种方法:追加
    */ $("#image img").attr("src" , data.url );
    });
    }
    } ); })
    • 那么后端的low代码如下:
    	import com.alibaba.fastjson.JSON;
    
    	import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.Part;
    import java.io.File;
    import java.io.IOException;
    import java.time.LocalDate;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Date;
    import java.util.HashMap; // @MultipartConfig 注解就是文件注解,要获取前端的文件信息,必须加这个注解,不然做的所有事情都是无用功
    @MultipartConfig
    @WebServlet("/ajax/upload.do")
    public class UploadServlet extends HttpServlet { @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /*
    * 想要构建的是这么一个玩意儿
    * "errno":0 data:[ { url:"图片地址“ } , { alt:"图片说明“ } , { href:"null" } ]
    *
    * */ ArrayList<Object> list = new ArrayList<>(); Collection<Part> parts = req.getParts(); // 这是获取前台上传的文件 for (Part part : parts) { // 先构建 data:[ { } , { } ]中的[ { } , { } ] // 获取文件的全路径
    // 但是:不同浏览器的这个全路径都不一样,所以需要截取从而自定义文件名
    String filePath = part.getSubmittedFileName();
    // System.out.println(filePath);
    // 截取文件的后缀名
    int subFileName = filePath.lastIndexOf(".");
    String fileSuffix = filePath.substring(subFileName); // 自己给文件重新定义一个名字,并规定存放的地方
    String timeStr = LocalDate.now().toString(); // 获取当前项目的一个指定文件夹名字,用来保存文件 注意:getRealPath这是获取的当前项目的全路径,即:从盘符开始的路径
    String proPathName = this.getServletContext().getRealPath("/upload/" + timeStr );
    File file = new File(proPathName);
    if ( !file.exists() ){
    file.mkdirs();
    } // 拼接文件后缀名并保存文件
    long timeStamp = new Date().getTime();
    part.write(proPathName + "/" + timeStamp + fileSuffix ); HashMap<String, String> map = new HashMap<>();
    map.put( "url" , "/upload/" + timeStr + "/" + timeStamp + fileSuffix );
    map.put( "alt" , timeStamp + fileSuffix );
    map.put( "href" , null );
    list.add(map);
    } // 再构建"errno":0 data:[ { url:"图片地址“ } , { alt:"图片说明“ } , { href:"null" } ]
    HashMap<String, Object> map = new HashMap<>();
    map.put("errno", "0");
    map.put("data", list); resp.getWriter().print( JSON.toJSONString(map) );
    }
    }

文件下载

  • 后端low代码如下
	import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder; @WebServlet("/downFile")
public class downFileInClientServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1、获取让浏览器下载的文件路径
String FileRealPath = "D:\\JavaTrainStudy\\servlet\\out\\production\\study06-httpServletResponse\\loginbg.png"; // 2、告知浏览器要下载的文件名是什么?
String fileName = FileRealPath.substring( FileRealPath.lastIndexOf("\\") + 1 ); // 3、让浏览器支持文件下载
// Content-Disposition这个就是让浏览器支持文件下载
// URLEncoder.encode( String s , String enc ) 是为了以防文件名是中文名,这样就设置编码格式了,让浏览器能够解析这个中文文件名
resp.setHeader("Content-Disposition" , "attachment ; filename=" + URLEncoder.encode(fileName , "utf-8")); // 4、获取输入、输出流对象 并 把服务器中的文件输出到浏览器上
FileInputStream fis = new FileInputStream( FileRealPath );
ServletOutputStream os = resp.getOutputStream(); // 创建缓冲区
int len = 0 ;
byte[] buffer = new byte[1024];
while ( ( len = fis.read( buffer ) ) > 0 ){
os.write( buffer , 0 , len);
} // 5、关闭流管道
if ( os != null ){
os.close();
}
if ( fis != null ){
fis.close();
} }
}

分布式文件系统

  • 优点

    • 解决了传统方式的单点故障问题
    • 若某一个节点出现故障,则还有其他的节点可以用来读取和写入文件
    • 提供数据备份从而避免磁盘损坏而导致的文件丢失
    • 提供扩容机制,无限增加文件存放的空间上限

1.2、认识FastDFS

补充:常见的分布式文件系统

  • FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS

1.2.1、了解FastDFS

  • 官网:https://github.com/happyfish100/fastdfs
  • FastDFS是一个开源的轻量级分布式文件系统,为互联网应用量身定做,简单、灵活、高效,采用C语言开发,由阿里巴巴开发并开源
  • FastDFS对文件进行管理,功能包括:文件存储、文件同步( 指的是:文件系统 和 数据备份之间的同步 )、文件上传、文件下载、文件删除等
  • FastDFS解决了大容量文件存储的问题
  • FastDFS特别适合以文件为载体的在线服务,如相册网站、文档网站、图片网站、视频网站等
  • FastDFS充分考虑了冗余备份、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务
    • 冗余备份:指的是文件系统中存的文件 和 数据备份中存的文件完全一致的问题

    • 线性扩容:文件系统 和 数据备份不断增加呗( 就是上图中再加几份嘛 ),和水平扩容类似

1.2.2、FastDFS的组成结构

  • 由两大部分构成,一个是客户端,一个是服务端

    • 客户端:指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端。FastDFS提供专有API访问,目前提供了C、Java和PHP几种编程语言的API,用来访问FastDFS文件系统
    • 服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)
      • 跟踪器 tracker:这个玩意儿类似于Erueka / zookeeper注册中心,起到一个调度的作用。它是在内存中记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽,因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group,group指的就是:文件系统 和 数据备份的组合,这二者就是一个group)中有3台就足够了
      • 存储节点 storage:用于存储文件,包括文件和文件属性(meta data,如:文件名、文件大小、文件后缀...)都保存到存储服务器磁盘上。以及完成文件管理的所有功能:文件存储、文件同步和提供文件访问( 上传、下载、删除 )等

2、开始玩FastDFS

2.1、安装FastDFS

  • 注:我的系统是centos 7

  • 安装需要的依赖环境 gcc、libevent、libevent-devel

yum install gcc libevent libevent-devel -y

  • 安装公共函数库libfastcommon 和 fastDFS压缩包

    • 自行去前面官网中进行下载,当然:官网的wiki中有在线拉取命令

  • 加压公共函数库libfastcommon
tar -zxvf libfastcommon-1.0.36.tar.gz

  • 进入libfastcommon,执行里面的make.sh,编译公共函数
./make.sh

# 当然:可以把命令进行合并 执行如下命名 就是编译并安装
./make.sh && ./make.sh install

  • 安装公共函数
./make.sh install

  • 解压缩fastdfs-5.11.tar.gz压缩包
tar -zxvf fastdfs-5.11.tar.gz

  • 进入解压之后的文件,使用make sh进行编译
./make.sh

# 一样的可以用组合命令 即:编译并安装
./make.sh && ./make.sh install
  • 安装
./make.sh install

  • 检查是否安装成功,进入如下的目录即可
cd /usr/bin

  • 往后找,出现这些fdfs开头的文件就表示成功( 这些文件就是fastDFS的相关命令 )

  • fastDFS配置文件所在地,进入如下目录即可
  • 想要让fastDFS的配置文件生效,那么就需要放到下面的这个目录中
cd /etc/fdfs

  • 拷贝两个配置文件到etc/fdfs中,这两个配置文件在解压的fastDFS的conf中,一个叫http.conf,一个叫mime.types
# 供nginx访问使用
cp http.conf /etc/fdfs # 供nginx访问使用
cp mime.types /etc/fdfs

2.2、启动FastDFS

  • 这个玩意儿不可以直接启动,因为默认的配置文件中有一些关于文件目录的配置是不存在的,因此:只要直接启动就会报错

2.2.1、修改配置文件

  • 要修改的文件就两个

  • 以防万一,因此:将上面的文件拷贝一份
/etc/fdfs

mv storage.conf.sample ./storage.conf

mv tracker.conf.sample ./tracker.conf

2.2..1.1、修改tracker.conf

  • 在这个配置文件中有一个base_path配置,指向的是fastDFS作者余庆的地址,而我们自己的linux中并没有这个目录,因此:做修改
vim tracker.conf

# 搜索此配置
/base_path # 改成的值,也可以自定义自己的目录( 注意:需要保证这个目录必须存在,没存在那就需要创建 )
base_path=/opt/fastdfs/tracker
  • 注意:需要保证这个目录必须存在,没存在那就需要创建

2.2.1.2、修改storage.conf

  • 需要改的内容如下
# storage存储数据目录
base_path=/opt/fastdfs/storage # 真正存放文件的目录
store_path0=/opt/fastdfs/storage/files # 注册当前存储节点的跟踪器地址
tracker_server=服务器ip:22122
  • 注意:要是前面的那三个目录没有的话,记得创建,若指向的是已经创建好的目录,那就不用创建了
mkdir -p /opt/fastdfs/tracker

mkdir -p /opt/fastdfs/storage

mkdir -p /opt/fastdfs/storage/files

2.2.2、开启fastDFS

  • 在任意目录下,执行如下的命令即可
# 启动tracker 要想看fdfs_trackerd的命令用法,那直接输入fdfs_trackerd就可以弹出其用法了
# 如:要关闭tracker,则命令为:fdfs_trackerd /etc/fdfs/tracker.conf stop
# 开启 | 重启就是把stop改成start | restart即可
fdfs_trackerd /etc/fdfs/tracker.conf # 启动storage
fdfs_storaged /etc/fdfs/storage.conf
  • 查看是否启动成功
ps -ef | grep fdfs

  • 如下图表示启动成功

  • 但是上面的启动会有坑儿,所以需要确认一把
# 查看日志文件是否有报ERROR
cd /opt/fastdfs/storage/logs/storage.log
  • 若是发现日志中报的是如下信息
ERROR - file: storage_ip_changed_dealer.c, line: 180, connect to tracker server 服务器ip:22122 fail, errno: 110, error info: Connection timed out

即:链接超时

  • 这种情况一般都是22122端口没开放
# 开放22122端口
firewall-cmd --zone=public --add-port=22122/tcp --permanent # 重启防火墙
systemctl restart firewalld.service # 当然:要是云服务器的话,直接在web管理界面的管理中添加规则( 开放22122端口 ) 即可

2.2.3、查看默认创建的文件数

  • 进入如下的目录
cd /opt/fastdfs/storage/files/data

  • 这里面有526个文件夹,而每一个文件夹里面又有526个文件夹,即256 * 256个文件夹,总的文件夹数目为6万多个

    • 这256 * 256个文件夹的作用:解决的就是如下的问题

    • 而fastDFS就是使用那256 * 256个文件夹,把文件分别放入哪些文件夹中,这样就让搜索变得方便了

2.2.4、测试FastDFS

2.2.4.1、测试上传文件

  • 要能进行测试的话,需要修改一个配置文件,因为这个配置文件中的配置信息是作者余庆的

  • 要修改的内容如下:
# 注意:这个目录也要保证存在,不存在就是创建 mkdir -p /opt/fastdfs/client
base_path=/opt/fastdfs/client tracker_server=自己服务器ip:22122
  • 搞一个用来测试上传的文件

  • 执行文件上传命令

    • 可以使用如下命令看一下测试文件上传命令是怎么写的

      • fdfs_test
        
        

  • 提取出测试命令语法
fdfs_test <config_file> <operation>
operation: upload, download, getmeta, setmeta, delete and query_servers
# <> 表示必填 # 因此:在测试中,文件上传的指令为:
fdfs_test /etc/fdfs/client.conf upload /root/hello-fastdfs.txt

  • 注意:防火墙的问题啊,要是报:connect to 162.14.66.60:23000 fail, errno: 113, error info: No route to host,这就是防火墙没开放23000端口,打开就可以了
# 开放23000端口
firewall-cmd --zone=public --add-port=23000/tcp --permanent # 刷新防火墙
systemctl restart firewalld.service
  • 上面成功之后有一堆信息,很重要
This is FastDFS client test program v5.11

Copyright (C) 2008, Happy Fish / YuQing

FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit. # 这个是说访问fastdfs的主页网址 - 目前还不能访问,需要后面弄
Please visit the FastDFS Home Page http://www.csource.org/
for more detail. # 这是配置的client.conf中的信息
[2022-06-01 10:17:07] DEBUG - base_path=/opt/fastdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 tracker_query_storage_store_list_without_group:
server 1. group_name=, ip_addr=162.14.66.60, port=23000 group_name=group1, ip_addr=162.14.66.60, port=23000
storage_upload_by_filename
# 重要的信息在这里group_name、remote_filename
# group_name就是组名,在前面配置中见过它,就是说的文件系统 和 数据备份这二者的组合名
# remote_filename 远程文件名 这是关键中的关键,告知你:文件保存到那里去了
group_name=group1, remote_filename=M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
source ip address: 10.0.0.16
file timestamp=2022-06-01 10:17:07
file size=641
file crc32=1141168436
example file url: http://162.14.66.60/group1/M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt
source ip address: 10.0.0.16
file timestamp=2022-06-01 10:17:07
file size=641
file crc32=1141168436
example file url: http://162.14.66.60/group1/M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt
  • 单独说明:remote_filename
remote_filename=M00/00/00/

M00 指的是:/opt/fastdfs/storage/files/data			就是前面去看默认创建文件数( 256 * 256 )的位置,跟前面的配置有关啊

00/00/ 指的就是:/opt/fastdfs/storage/files/data目录下的00子目录,这里面的00目录

CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt  指的是:保存的文件名  fastdfs会重新生成文件名,以防的就是同名文件,造成附件覆盖的问题

  • 上图中几个文件解读
# _big 就是数据备份文件
# ——m 就是meta data文件,即:文件属性文件( 文件名、文件后缀、文件大小..... )
-rw-r--r-- 1 root root 641 Jun 1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt
-rw-r--r-- 1 root root 49 Jun 1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt-m # 这两个就是文件系统中的文件
-rw-r--r-- 1 root root 641 Jun 1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
-rw-r--r-- 1 root root 49 Jun 1 10:17 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt-m # CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt 和 文件系统中的CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt存的内容是一样的 # CgAAEGKWzCOACGE1AAACgUQE2TQ590_big.txt-m 和 CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt-m这两个备份文件也是相应的

2.2.4.2、测试文件下载和删除
  • 前面已经见过对应的语法了
fdfs_test <config_file> <operation>
operation: upload, download, getmeta, setmeta, delete and query_servers
# <> 表示必填
  • 变一下就可以了
# 变成下载的命令,然后使用此命令查看完整命令即可
fdfs_test /etc/fdfs/client.conf download # 根据执行上面的命令,得到文件下载的语法
fdfs_test <config_file> download <group_name> <remote_filename> # 那么想要下载刚刚上传的文件,执行如下的命令即可
fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
# 其中:group 和 remote_filename都在前面上传时见过了
# 注:这个下载是下载到当前所在目录的位置 # 同理:就可以得到文件删除的命令了
fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/CgAAEGKWzCOACGE1AAACgUQE2TQ590.txt
  • 以上这些fdfs_test只会在测试时使用,其他地方基本上都不用的

2.3、安装Nginx

  • 上传fastdfs-niginx扩展模块 并 解压 - 使用官网中wiki说明的命令拉取也行

  • 安装nginx,要是有的话就跳过

  • 注意点:nginxfastdfs-nginx放到/usr/local目录下,不然可能会出现莫名其妙的问题

  • 记住两个目录
# nginx安装目录
/usr/local/nginx_fdfs # fastdfs-nginx模块的src目录
/usr/local/fastdfs-nginx-module-master/src

  • 进入nginx安装目录,进行模块添加配置
# 进入nginx安装目录
cd nginx_fdfs # 执行模块配置
# prefix 就是前面让记住的nginx安装目录 add-module就是fastdfs-nginx模块的src目录
./configure --prefix=/usr/local/nginx_fdfs --add-module=/usr/local/fastdfs-nginx-module-master/src
  • 编译并安装
# 在安装的nginx目录下载执行下述命令
make & make install

  • 注释事项:Nginx的安装需要Linux安装相关的几个库,否则编译会出现错误,有这几个的话就不安装了
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y

2.3.1、修改需要的配置文件

  • 将fastdfs-nginx扩展模块中的mod_fastdfs.conf文件复制到/etc/fdfs
cp /usr/local/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs

  • 修改/etc/fdfs/mod_fastdfs.conf
vim mod_fastdfs.conf

# 修改内容如下:
# 这个目录要保证存在,不存在就要配置好了创建它 mkdir -p /opt/fastdfs/nginx_mod
base_path=/opt/fastdfs/nginx_mod tracker_server=自己服务器ip:22122 # 访问地址是否带上组名
url_have_group_name = true store_path0=/opt/fastdfs/storage/files
  • 上面base_path目录要是不存在记得创建

  • 进入nginx_fdfs的安装目录中,去nginx.conf中配置fastdfs-nginx的扩展模块
# 编辑nginx.conf文件
vim /usr/local/nginx_fdfs/conf/nginx.conf # 配置内容
location ~ /group[1-9]/M0[0-9] {
ngx_fastdfs_module;
} # 解读:ngx_fastdfs_module
# 这个指令不是Nginx本身提供的,是扩展模块提供的,根据这个指令找到FastDFS提供的Nginx模块配置文件,然后找到Tracker,最终找到Stroager

  • 启动nginx
/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf  -t

/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf

# 保险起见,查看nginx是否启动成功
ps -ef | grep nginx

  • 注意:这里很容易出现启动不起来,如果下面这个进程没有启动起来
nobody    3895  3894  0 15:45 ?        00:00:00 nginx: worker process

  • 那么:就去查看日志文件
cd /usr/local/nginx_fdfs/logs

# 还有一份日志中也可能出现错误信息
cd /opt/fastdfs/nginx_mod

2.4、Java操作FastDFS

2.3.2、扩展模块执行流程

  • 下面这个流程很重要,涉及到后面的知识

2.4.1、文件上传

  • resources目录下创建fastdfs.conf文件,并编写如下内容:
tracker_server=服务器ip:22122

  • 编写文件上传代码
package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*; import java.io.IOException; /**
* @author : ZiXieQing
* @version : V1.0.0
* @className : UploadFile
* @description : 该类功能 FastDFS文件上传
* @packageName : com.zixieqing
*/ public class UploadFile { public static void main(String[] args) { TrackerServer trackerServer = null;
StorageServer storageServer = null;
try {
// 1、初始化配置文件
ClientGlobal.init("fastdfs.conf"); // 2、创建tracker客户端
TrackerClient trackerClient = new TrackerClient();
// 3、获取trackerServer
trackerServer = trackerClient.getConnection();
// 4、获取storageServer
storageServer = trackerClient.getStoreStorage(trackerServer); // 5、创建storage客户端 - 这个对象就是用来上传文件、下载文件、删除文件的
StorageClient storageClient = new StorageClient(trackerServer, storageServer); // 6、上传文件
/*
这里有两个API需要了解
String[] upload_file(byte[] file_buff, int offset, int length, String file_ext_name, NameValuePair[] meta_list)
这个API常用来web中上传文件的
参数1 file_buff、文件字节
offset、length、从文件的那个位置开始上传,截止位置
参数4 file_ext_name、文件后缀
参数5 meta_list、文件的属性文件 String[] upload_file(String local_filename, String file_ext_name, NameValuePair[] meta_list)
这个API是上传本地文件的
参数1 local_filename、本地文件的绝对路径
参数2 file_ext_name、文件后缀名
参数3 meta_list、文件的属性文件,linux1中的哪个meta data,一般都不传 上述这两个API,注意返回值,这个String[] 很重要,就是涉及到linux中的那个组名group 和 远程文件名remote_filename
*/
String[] result = storageClient.upload_file("C:\\Users\\ZiXieQing\\Desktop\\图库\\19.jpg", "jpg", null); // 7、验证一下
for (String data : result) {
System.out.println("data = " + data);
} } catch (IOException e) {
throw new RuntimeException(e);
} catch (MyException e) {
throw new RuntimeException(e);
} finally {
// 8、释放资源
if (storageServer != null) {
try {
storageServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (trackerServer != null) {
try {
trackerServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}

  • 浏览器访问

2.4.2、文件下载

  • 把前面的文件上传代码改一下即可,换成另一个API而已
package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*; import java.io.IOException; /**
* @author : ZiXieQing
* @version : V1.0.0
* @className : DownloadFile
* @description : 该类功能 fastDFS文件下载
* @packageName : com.zixieqing
*/ public class DownloadFile { public static void main(String[] args) { TrackerServer trackerServer = null;
StorageServer storageServer = null;
try {
// 1、初始化配置文件
ClientGlobal.init("fastdfs.conf"); // 2、获取tracker客户端
TrackerClient trackerClient = new TrackerClient();
// 3、获取trackerServer
trackerServer = trackerClient.getConnection();
// 4、获取storageServer
storageServer = trackerClient.getStoreStorage(trackerServer); // 5、创建storage客户端
StorageClient storageClient = new StorageClient(trackerServer, storageServer); // 6、下载文件
/*
这里需要知道两个API
byte[] download_file(String group_name, String remote_filename)
这个API常用于web操作 int download_file(String group_name, String remote_filename, String local_filename)
这个API是把文件下载到本地磁盘中
这个API的返回值结果很重要
*/
String group = "group1";
String remoteFileName = "M00/00/00/CgAAEGKYRg-AAIrWAAD8cA4U6dY771.jpg";
// 存入本地磁盘路径+存入磁盘的文件名
String localFileName = "d:/靓妹.jpg";
// 只有返回值是0才表示下载成功,否则只要是其他数字都是下载失败( 其他数字有可能是组名错了,远程文件名错了........
int result = storageClient.download_file(group, remoteFileName, localFileName); // 7、验证
System.out.println("result = " + result);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (MyException e) {
throw new RuntimeException(e);
} finally {
// 8、释放资源
if (storageServer != null) {
try {
storageServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (trackerServer != null) {
try {
trackerServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} }
}

2.4.3、文件删除

package com.zixieqing;

import org.csource.common.MyException;
import org.csource.fastdfs.*; import java.io.IOException; /**
* @author : ZiXieQing
* @version : V1.0.0
* @className : DeleteFile
* @description : 该类功能 FastDFS删除文件
* @packageName : com.zixieqing
*/ public class DeleteFile { public static void main(String[] args) { TrackerServer trackerServer = null;
StorageServer storageServer = null;
try {
// 1、初始化配置文件
ClientGlobal.init("fastdfs.conf"); // 2、获取tracker客户端
TrackerClient trackerClient = new TrackerClient();
// 3、获取trackerServer
trackerServer = trackerClient.getConnection();
// 4、获取storageServer
storageServer = trackerClient.getStoreStorage(trackerServer);
// 5、获取storage客户端
StorageClient storageClient = new StorageClient(trackerServer, storageServer); // 6、执行文件删除
/*
int delete_file(String group_name, String remote_filename)
参数1 group_name、组名
参数2 remote_filename、远程文件名
*/
// 一样的,返回值是0就表示成功,其他都是删除失败
int result = storageClient.delete_file("group", "M00/00/00/CgAAEGKYRg-AAIrWAAD8cA4U6dY771.jpg"); // 7、验证一下
System.out.println("result = " + result); } catch (IOException e) {
throw new RuntimeException(e);
} catch (MyException e) {
throw new RuntimeException(e);
}finally {
// 8、释放资源
if (storageServer != null) {
try {
storageServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (trackerServer != null) {
try {
trackerServer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}

FastDFS 技术整理的更多相关文章

  1. C#进程间通讯技术-整理。

    原文:C#进程间通讯技术-整理. 扩展阅读:http://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html 一.进程间通讯的方式 1) ...

  2. canvas技术整理

    canvas技术整理 html <canvas id= "canvas"></canvas> javascript var canvas = documen ...

  3. DBGrid相关技术整理

    DBGrid相关技术整理: 注:对于DBGrid相关属性.方法的学习融入到技术整理过程中 一,多选 设置属性: Options->dgMultiSelect = True; ->dgRow ...

  4. Java成神之路技术整理(长期更新)

    以下是Java技术栈微信公众号发布的关于 Java 的技术干货,从以下几个方面汇总. Java 基础篇 Java 集合篇 Java 多线程篇 Java JVM篇 Java 进阶篇 Java 新特性篇 ...

  5. Java成神之路技术整理

    关于 Java 的技术干货,从以下几个方面汇总. Java 基础篇 Java 集合篇 Java 多线程篇 Java JVM篇 Java 进阶篇 Java 新特性篇 Java 工具篇 Java 书籍篇 ...

  6. 51建设Android版一些技术整理

    不知不觉几个月就过去了,新项目已经发了两个大的版(其实已经迭代了3版),趁着项目新版刚刚上线闲下来的时间整理下用到的技术点. 整体架构 采用MVP Android官方MVP架构示例项目解析 推荐一个插 ...

  7. 基于.NET平台常用的框架技术整理

    个人整理 部分收藏于:http://www.cnblogs.com/hgmyz/p/5313983.html 自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线 ...

  8. 长年承接AR图像识别项目,关于高速UnityARCam多图问题技术整理

    //关于高通ARCameraQCARBehaviour script下 Max Simultneous Image QCARBehaviour script下 Max Simultneous Imag ...

  9. 初识-Android之智能短信项目相关技术整理

    标签页切换采用传统的TabHost: 采用TabActivty实现TabHost. 效果图-后补: 相关技术详解推荐: http://blog.csdn.net/zhouli_05/article/d ...

随机推荐

  1. vue简单的父子组件之间传值

     todo-list为例子: 代码: 父传子--------------属性  v-bind 子传父--------------$emit <!DOCTYPE html> <html ...

  2. 面试官:Zookeeper怎么解决读写、双写并发不一致问题,以及共享锁的实现原理?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天清明假期,赶上北京玉渊潭公园 ...

  3. 02 | 自己动手,实现C++的智能指针

    第一步:针对单独类型的模板 为了完成智能指针首先第一步的想法. class shape_wrapper { public: explicit shape_wrapper( shape* ptr = n ...

  4. 我们如何上传docker到habor上呢

    Docker 打包上传habor认证 首先在 Maven 的配置文件 setting.xml 中增加相关 server 配置,主要配置 Docker registry(远程仓库)用户认证信息. < ...

  5. java数组算法——数组元素的赋值2

    java数组算法--数组元素的赋值2--java经典面试题:创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值.同时要求元素时的值各不相同

  6. 重定向管道流读取TXT文本第一次读取为""空字符串、type xxx.txt | go run . 报错、BOM头、[239,186,191] 字节数组

    重定向管道流读取TXT文本第一次读取为""空字符串.type xxx.txt | go run . 报错.BOM头.[239 186 191] 字节数组

  7. 2021.11.04 P1392 取数(多路归并)

    2021.11.04 P1392 取数(多路归并) P1392 取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 在一个n行m列的数阵中,你须在每一行取一个数(共n个数) ...

  8. 通过实例程序验证与优化谈谈网上很多对于Java DCL的一些误解以及为何要理解Java内存模型

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  9. esp8266 esp01s wifi继电器 初步点灯成功!艰难的历程啊,期间差点烧了

    0x00 前言说明 放假这几天,在淘宝买了esp01s,和一个搭配esp01s的wifi继电器准备做一些IOT(物联网)实验,踩了不少的坑,总算是点灯成功了!下面记录一些实验的拍照吧~ 继电器参数说明 ...

  10. 三月总结&四月计划

    三月总结 1. 主要任务 <C++设计模式>网课 ① 进展: 看完,对设计模式的整体设计思路和几个重要的设计模式重点学习了一下,目前对设计模式的认识还比较浅 ② 总结: 做完总结 ③ 反思 ...