FastDFS 分布式文件系统安装与使用

环境准备
# 关闭防火墙
systemctl disable --now firewalld
systemctl disable --now dnsmasq
systemctl disable --now NetworkManager

# 关闭selinux
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config

# 关闭分区
swapoff -a && sysctl -w vm.swappiness=0
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab

yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y
磁盘目录
mkdir /home/dfs #创建数据存储目录
cd /usr/local/src #切换到安装目录准备下载安装包
安装 libfastcommon
git clone https://github.com/happyfish100/libfastcommon.git --depth 1
cd libfastcommon/
./make.sh && ./make.sh install #编译安装
安装 FastDFS
cd ../ #返回上一级目录
git clone https://github.com/happyfish100/fastdfs.git --depth 1
cd fastdfs/
./make.sh && ./make.sh install #编译安装
#配置文件准备
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用
cp /usr/local/src/fastdfs/conf/http.conf /etc/fdfs/ #供nginx访问使用
cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs/ #供nginx访问使用
安装 fastdfs-nginx-module
cd ../ #返回上一级目录
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
安装 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 #编译安装
tracker配置(单机版)
#服务器ip为 192.168.52.1
#我建议用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.1:22122  # tracker服务器IP和端口
http.server_port=8888  # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
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
配置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.182.128: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;
    }
}
tracker(启动、重启、停止)
/etc/init.d/fdfs_trackerd start #启动tracker服务
/etc/init.d/fdfs_trackerd restart #重启动tracker服务
/etc/init.d/fdfs_trackerd stop #停止tracker服务
chkconfig fdfs_trackerd on #自启动tracker服务
storage(启动、重启、停止)
/etc/init.d/fdfs_storaged start #启动storage服务
/etc/init.d/fdfs_storaged restart #重动storage服务
/etc/init.d/fdfs_storaged stop #停止动storage服务
chkconfig fdfs_storaged on #自启动storage服务
nginx(启动、重启、停止)
/usr/local/nginx/sbin/nginx #启动nginx
/usr/local/nginx/sbin/nginx -s reload #重启nginx
/usr/local/nginx/sbin/nginx -s stop #停止nginx

# 访问
http://192.168.86.128:8888/group1/M00/00/00/wKjfgl3ijiWATv7JAAA0OhyYlyM226.png
检测集群
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
集成 SpringBoot

pom.xml

<!-- FastDFS分布式文件系统 -->
        <!-- https://mvnrepository.com/artifact/com.github.tobato/fastdfs-client -->
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.2</version>
        </dependency>

application.yml

server:
  port: 8001

spring:
  servlet:  #限制文件上传配置
    multipart:
      enabled: true                     #启用文件上传功能
      max-file-size: 10MB               #设置单个文件的大小
      max-request-size: 20MB            #设置文件总大小
      file-size-threshold: 512KB        #当文件超过指定的大小时会返回磁盘
      location: /                       #设置文件上传的临时路径


#配置FastDFS
fdfs:
  so-timeout: 2500        #请求超时时间
  connect-timeout: 600    #连接超时时间
  thumb-image:            #缩略图大小
    height: 60
    width: 60
  tracker-list:  #tracker地址
    - 192.168.223.130:22122

boot:
  upload:
    baseUrl: http://192.168.86.128/
    allowTypes:
      - image/jpeg
      - image/png
      - image/bmp
      - image/jpg

FastDFSClientImporter.java

/**
 * @className: FastDFSClientImporter
 * @author: q-linyu
 * @description: FastDFS客户端注入组件类
 * 解决JMX重复注册Bean的问题:@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
 * @date: 2021/7/18 01:45
 * @version: 1.0
 **/
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)
public class FastDFSClientImporter {

}

UploadProperty.java

/**
 * @className: upload
 * @author: q-linyu
 * @description: 图片属性配置类
 * @date: 2021/7/18 01:49
 * @version: 1.0
 **/
@Data
@Component
@ConfigurationProperties(prefix="boot.upload")
public class UploadProperty {

    /**
     * 路径
     */
    private String baseUrl;

    /**
     * 图片格式类型
     */
    private List<String> allowTypes;
}

FastDFSUtils.java

/**
 * @className: FastDFSUtils
 * @author: q-linyu
 * @description: 分布式文件系统工具类
 * @date: 2021/7/18 01:40
 * @version: 1.0
 **/
@Component
@EnableConfigurationProperties(UploadProperty.class)
public class FastDFSUtils {

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private UploadProperty uploadProperty;

    /**
     * 文件上传,并且上传后返回给文件的路径
     * @param files 要上传的目标路径
     * @return
     */
    public List<String> upload(List<MultipartFile> files){

        List<String> paths = new ArrayList<>();

        files.forEach(file -> {

            try {

                //校验文件格式
                String contentType=file.getContentType();
                if (!uploadProperty.getAllowTypes().contains(contentType)) {
                    // 错误消息的展示----无效的文件类型
                }

                //获取文件的名称
                String fileName=file.getOriginalFilename();

                //获取图片的后缀
                String prefixName=StringUtils.substringAfter(fileName, ".");

                //校验文件的内容
                BufferedImage image= ImageIO.read(file.getInputStream());
                if (image==null) {
                    // 错误消息的展示----无效的文件类型
                }

                //上传FastDFS文件服务器
                StorePath storePath=storageClient.uploadFile(file.getInputStream(), file.getSize(), prefixName, null);
                paths.add(uploadProperty.getBaseUrl()+storePath.getFullPath());

            }catch (IllegalStateException | IOException e) {
                //上传失败提示
                e.printStackTrace();
            }

        });

        return paths;
    }

    /**
     * 下载文件
     * @param filePath
     * @param request
     * @param response
     */
    public void download(String filePath, HttpServletRequest request , HttpServletResponse response){

        InputStream is = null;

        try {

            String[] paths = filePath.split("/");
            String groupName = null;
            for (String path : paths) {
                if (path.contains("group")){
                    groupName = path;
                    break;
                }
            }
            assert groupName != null;
            String path = filePath.substring(filePath.indexOf(groupName) + groupName.length() + 1);
            // 执行下载并返回流
            is = storageClient.downloadFile(groupName, path, inputStream -> inputStream);

            // 获取带后缀的文件名
            String fileName = paths[paths.length - 1];

            // 获取类型
            String contentType = request.getServletContext().getMimeType(fileName);
            String contentDisposition = "attachment;filename=" + fileName;

            // 设置请求头
            response.setHeader("Content-Type",contentType);
            response.setHeader("Content-Disposition",contentDisposition);

            // 获取客户端的流
            ServletOutputStream os = response.getOutputStream();

            // 输出
            IOUtils.copy(is,os);

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 删除文件
     * @param filePath
     */
    public void delete(String filePath){
        storageClient.deleteFile(filePath);
    }


}

UploadController.java

/**
 * @className: UploadController
 * @author: q-linyu
 * @description: 文件上传控制器
 * @date: 2021/7/18 01:51
 * @version: 1.0
 **/
@RestController
public class UploadController {

    @Autowired
    private FastDFSUtils fastDFSUtils;

    /**
     * 上传文件
     * @param files
     * @return
     */
    @PostMapping(value = "upload")
    public List<String> upload(@RequestParam(value = "files")List<MultipartFile> files){
        return fastDFSUtils.upload(files);
    }

    /**
     * 下载文件
     * @param filePath
     * localhost:8001/filePath=http://192.168.223.130/group1/M00/00/00/wKjfgl2oOQSAQXt8AAA0OhyYlyM329.png
     * @return
     */
    @GetMapping(value = "download")
    public void download(@RequestParam(value = "filePath")String filePath, HttpServletRequest request, HttpServletResponse response){
        fastDFSUtils.download(filePath,request,response);
    }


    /**
     * 删除文件
     * @param filePath
     * @return
     */
    @DeleteMapping(value = "delete")
    public void delete(@RequestParam(value = "filePath")String filePath){
        fastDFSUtils.delete(filePath);
    }
}

上一篇:FastDFS文件系统使用经验


下一篇:2021-07-16