likes
comments
collection
share

fastdfs 文件上传

作者站长头像
站长
· 阅读数 10

分布式文件上传

分别说到 FastDFS 和 MinIO

FastDFS

下载依赖

  1. libfastcommon 公共 C 函数库
  2. fastdfs fastdfs 核心项目
  3. fastdfs-nginx-module nginx 整合 fastdfs

打开 linux 安装C语言开发环境

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

安装 libevent

FastDFS 依赖 libevent 库

yum -y install libevent

安装 libfastcommon

上传资源 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

libfastcommon 默认安装在 /usr/lib64 和 /usr/include/fastcommon 两个目录中

并且会在 /usr/lib 目录中创建软链接。

fastdfs 文件上传

安装 FastDFS

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

# 解压 fastdfs 至当前所在目录
unzip fastdfs-master.zip

编辑和安装

# 进入解压后的 libfastcommon-master 目录
cd fastdfs-master
# 编译并安装
./make.sh install

安装成功将安装目录下的conf下的文件拷贝到/etc/fdfs/下。(感觉没用)

编译过程中,如果报错,致命错误:sf/sf_global.h:没有那个文件或目录)

缺少了 libserverframe 网络框架

FastDSF需要用centos7版本往上才能安装的

需要先安装网络框架 libserverframe

安装方式同上

  • fastdfs 默认安装在以下位置:
  • /usr/bin:可执行文件
  • /etc/fdfs:配置文件
  • /etc/init.d:主程序代码
  • /usr/include/fastdfs:插件组

tracker 和 storage 启动

tracker 和 storage 分别扮演不同的角色,都有自己的配置文件,分别启动

打开 /etc/fdfs 可以看到 tracker 和 storage 两个配置文件

  • client.config:客户端配置文件
  • storage.conf:存储器的配置文件
  • tracker.conf:跟踪器的配置文件

在 /etc/fdfs下

修改 tracker 配置文件

# 允许访问 tracker 服务器的 IP 地址,为空则表示不受限制
bind_addr =

# tracker 服务监听端口
port = 22122

# tracker 服务器的运行数据和日志的存储父路径(需要提前创建好)
base_path = /fastdfs/tracker

# tracker 服务器 HTTP 协议下暴露的端口
http.server_port = 8080

启动 tracker

/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

修改 storage 的配置文件

# 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

启动 storage

/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

client 配置

  • tracker 地址和之前定义一样
# client 客户端的运行数据和日志的存储父路径(需要提前创建好)
base_path = /fastdfs/client

# tracker 服务器的 IP 和端口
tracker_server = 192.168.10.101:22122

到 usr/bin 下执行上传

fdfs_test client配置路径 upload 将要上传的文件路径

整合 nginx

  1. 将 FastDFS-nginx-module 包传至 /usr/local/ 下
  2. 解压进去,讲 src 里面的 config 文件的 /usr/local 全部改为 /usr
  3. 将 mod_fastdfs.conf 拷贝至 /etc/fdfs/ 下
  4. 打开此文件,配置信息
# 存放文件
base_path=/opt/fastdfs/nginxFdFsLog
# tracker 的地址
tracker_server=192.168.134.222:22122
# 设置文件 URL 是否包含组名
url_have_group_name=true
store_path0=/home/FastDFS/fdfs_storage
# 群组名要和 storage 的一致
group_name=group1
  1. 安装 nginx 依赖
yum -y install pcre pcre-devel openssl openssl-devel zlib zlib-devel gcc
  1. 安装 nginx,解压到 uer/local/src 官网地址
  2. 到 nginx 目录进行配置,最后一行add-module 配置 fastdfs-nginx的src路径
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/usr/local/fastdfs-nginx-module-master/src
  1. 编译,先make,再使用 make install,之后再 usr/local/nginx
  2. 添加配置 nginx 服务器的 server,在 usr/local/src/nginx.../config/nginx.config
  3. 运行,之前已经将 nginx运行安装到了 ,usr/local/nginx中
  4. 到usr/local/nginx/sbin目录运行
  5. nginx -t 检查配置是否 ok
  6. 提示,没有此目录-- /var/temp/nginx/client,创建一下
  7. 将 /usr/local/fastdfs/config的 http.config 和 mime.types 拷贝到 /etc/fdfs/ 下,http 访问需要
  8. ./nginx 启动

注意:下面的location 后面的路径必须是 / 并且开头要加,否则访问不到

nginx 配置

server {
    listen       8888;
    server_name  192.168.134.222;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location /group1/M00 {
        ngx_fastdfs_module; # 安装的整合模块名
    }
}

Java 测试

依赖

<dependency>
    <groupId>net.oschina.zcx7878</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.27.0.0</version>
</dependency>

上传

@Test
void contextLoads() {
    try {
        // 加载配置文件
        ClientGlobal.initByProperties("fastdfs-client.properties");
        // 创建 tracker 客户端
        TrackerClient trackerClient = new TrackerClient();
        // 获取服务
        TrackerServer trackerServer = trackerClient.getConnection();
        StorageServer storageServer = null;
        // 定义 storage 客户端
        StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);
        // 文件元信息--可以加很多
        NameValuePair[] metaList = new NameValuePair[1];
        metaList[0] = new NameValuePair("fileName", "1.png");
        // 执行上传
        String file1 = storageClient.upload_file1("D:\\qq\\MTWG@_0$S[{KLGOU[O6~NA5.jpg", "jpg", metaList);
        System.out.println(file1); // 
        // 关闭
        trackerServer.close();
    } catch (IOException | MyException e) {
        throw new RuntimeException(e);
    }
}

开放 22122 和 23000 端口

sudo firewall-cmd --zone=public --add-port=22122/tcp --permanent
sudo firewall-cmd --zone=public --add-port=23000/tcp --permanent
# 重启端口
sudo firewall-cmd --reload

上传成功

kun/M00/00/00/wKhQgGS6TtaAdNf3AAEZO5jDrk0154.jpg

配置文件

## fastdfs-client.properties

fastdfs.connect_timeout_in_seconds = 5
fastdfs.network_timeout_in_seconds = 30

fastdfs.charset = UTF-8

fastdfs.http_anti_steal_token = false
fastdfs.http_secret_key = FastDFS1234567890
fastdfs.http_tracker_http_port = 80

fastdfs.tracker_servers = 192.168.80.128:22122

## 是否打开连接池,如果不打开,则每次创建一个新连接
fastdfs.connection_pool.enabled = true

## max_count_per_entry:每个主机的最大连接计数:端口,0不是限制
fastdfs.connection_pool.max_count_per_entry = 500

## 空闲时间超过此时间的连接将被关闭,单位:秒,默认值为3600
fastdfs.connection_pool.max_idle_time = 3600

## 达到最大连接数时的最大等待时间,单位为毫秒,默认值为1000
fastdfs.connection_pool.max_wait_time_in_ms = 1000

查询

try {
    // 加载配置文件
    ClientGlobal.initByProperties("fastdfs-client.properties");
    // 创建 tracker 客户端
    TrackerClient trackerClient = new TrackerClient();
    // 获取服务
    TrackerServer trackerServer = trackerClient.getConnection();
    StorageServer storageServer = null;
    // 定义 storage 客户端
    StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);
    // 查询方式一
    FileInfo info = storageClient
            .query_file_info("group1", "M00/00/00/wKiG3mS7KciAQCdvACb7kEitkFc114.png");
    System.out.println(info);
    // 查询方式二,直接查询
    FileInfo info1 = storageClient.query_file_info1("group1/M00/00/00/wKiG3mS7KciAQCdvACb7kEitkFc114.png");
    System.out.println(info1);
    // 查询元信息
    NameValuePair[] pairs = storageClient.get_metadata1("group1/M00/00/00/wKiG3mS7KciAQCdvACb7kEitkFc114.png");
    System.out.println(Arrays.toString(pairs));
    // 关闭
    trackerServer.close();
} catch (IOException | MyException e) {
    throw new RuntimeException(e);
}

下载

try {
    // 加载配置文件
    ClientGlobal.initByProperties("fastdfs-client.properties");
    // 创建 tracker 客户端
    TrackerClient trackerClient = new TrackerClient();
    // 获取服务
    TrackerServer trackerServer = trackerClient.getConnection();
    StorageServer storageServer = null;
    // 定义 storage 客户端
    StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

    // 下载
    byte[] bytes = storageClient.download_file1("group1/M00/00/00/wKiG3mS7KciAQCdvACb7kEitkFc114.png");
    FileOutputStream stream = new FileOutputStream(new File("C:\\Users\\坤\\Pictures\\2.png"));
    stream.write(bytes);
    stream.close();

    // 关闭
    trackerServer.close();
} catch (IOException | MyException e) {
    throw new RuntimeException(e);
}

概述

分布式文件系统:通过网络将一个一个计算机连接起来,组成文件系统

  • 扩容性
  • 持续性

主流的分布式文件系统

  1. NFS:网络文件系统

客户端 + 服务器,在客户端映射 nfs 的磁盘

  1. GFS:分块文件存储

主从结构,先将文件分块,存储到块服务器中,用户先访问 master 服务器,获取从那些块获取数据

  1. hdfs

分块存储,先访问 namenode 访问元数据,根据元数据从块中拿数据。

分布式服务提供商

OSS:阿里提供的

七牛云存储

百度云存储

fastdfs

由 C 语言编写的开源的分布式文件系统,由余庆编写并开源

是专用文件系统,适合存储小文件,也不分块,性能高,复杂性低

分为 tracker 和 storage

tracker 管理很多的 storage

用户先访问 tracker ,tracker根据情况返回 storage 存储的图片上传路径

tracker 和 storage 都可以部署集群

storage 向 tracker 上报自己状态

文件上传流程

fastdfs 文件上传

文件下载流程

fastdfs 文件上传

http://192.168.80.128/kun/M00/00/00/wKhQgGS6C2CAOP_uAAGADZNFMQg5288901_big
  • ip 地址
  • 组名:一个 storage
  • M00:虚拟路径
  • 后面都是文件路径

文件上传前后端

文件类

public class FileSystem {
    private String fileId;
    private String filePath;
    private String fileSize;
    private String fileName;
    private String fileType;
}

controller

fastdfs-upload:
  location: D:/upload

前端上传图片处理

这里需要处理一下跨域

<el-upload
  action="/api/fileServer/upload"
  list-type="picture-card"
  :on-preview="handlePictureCardPreview">
  <i class="el-icon-plus"></i>
</el-upload>

前端将图片上传到后端,后端保存到本地,并上传服务器。返回文件对象

@RestController
@RequestMapping("/fileServer")
public class FileServerController {

    @Value("${fastdfs-upload.location}")
    private String upload_location;

    /**
     * 将文件存储到本机上,调用 fastdfs 将文件上传到服务器
     */
    @PostMapping("/upload")
    public FileSystem upload(MultipartFile file) throws IOException {
        // 获取原始名称
        String filename = file.getOriginalFilename();
        // 扩展名
        String extention = filename.substring(filename.lastIndexOf("."));
        // 存到本机的名字
        String fileNameNew = UUID.randomUUID() + extention;
        // 存入本机
        File file1 = new File(upload_location + fileNameNew);
        file.transferTo(file1);
        // 获取本机的路径
        String newFilepath = file1.getAbsolutePath();
        FileSystem system;
        try {
            // 加载配置文件
            ClientGlobal.initByProperties("fastdfs-client.properties");
            // 创建 tracker 客户端
            TrackerClient trackerClient = new TrackerClient();
            // 获取服务
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = null;
            // 定义 storage 客户端
            StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

            // 文件元信息--可以加很多
            NameValuePair[] metaList = new NameValuePair[1];
            metaList[0] = new NameValuePair("fileName", filename);
            // 执行上传,扩展名为null,是因为解决重复添加扩展名。
            String fileFdfs = storageClient.upload_file1(newFilepath, null, metaList);
            system = new FileSystem(fileFdfs, fileFdfs, file.getSize(), fileNameNew, file.getContentType());
            System.out.println(fileFdfs);
            // 关闭
            trackerServer.close();
        } catch (IOException | MyException e) {
            throw new RuntimeException(e);
        }
        return system;
    }
}