FastDFS的简单使用

互联网中有海量的文件,比如电商网站有海量的图片文件,视频网站有海量的视频文件,如果使用传统的模式上传文件,肯定是不可取的。因此需要使用第三方服务器来存储图片 。

一.FastDFS简介

FastDFS 是用 c 语言编写的一款开源的分布式文件系统。FastDFS 为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。

Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。

Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。

服务端两个角色:

Tracker:管理集群,tracker 也可以实现集群。每个 tracker 节点地位平等。收集 Storage 集群的状态。

Storage:实际保存文件 Storage 分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员, 组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。

文件上传流程

文件下载流程:

二.FastDFS的入门

使用FastDFS上传文件,我们以图片的上传为例(ssm环境)

第一步:在Spring项目中导入FastDFS的坐标

<!-- 分布式文件系统 -->
<dependency>
    <groupId>org.csource.fastdfs</groupId>
    <artifactId>fastdfs</artifactId>
    <version>1.2</version>
</dependency>
<!-- 文件上传组件 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

第二步:导入FastDFS的配置(resources/config/fdfs_client.conf)

# connect timeout in seconds
# default value is 30s
connect_timeout=30

# network timeout in seconds
# default value is 30s
network_timeout=60

# the base path to store log files
base_path=/home/fastdfs

# tracker_server can ocur more than once, and tracker_server format is
#  "host:port", host can be hostname or ip address
tracker_server=192.168.25.133:22122

#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info

# if use connection pool
# default value is false
# since V4.05
use_connection_pool = false

# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time = 3600

# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false

# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id = false

# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename = storage_ids.conf

#HTTP settings
http.tracker_server_port=80

#use "#include" directive to include HTTP other settiongs
##include http.conf

第三步:编写UploadController

/**
 * 图片上传的处理器
 * @author Mr.song
 * @date 2019/06/09 20:07
 */
@RestController
public class UploadController {
  // FastDFS服务器的ip地址
    private String server_url = "http://192.168.25.133/";

    @RequestMapping("/upload")
    public Result uploadFile(MultipartFile uploadFile) {
        //把file存到fastDFS上
        try {
            String fileName = uploadFile.getOriginalFilename();
            //获取文件扩展名称
            String exeName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //创建上传客户端(封装的工具,见第六步)
            FastDFSClient client = new FastDFSClient("classpath:config/fdfs_client.conf");
            //完成上传,获得fileId
            String fileId = client.uploadFile(uploadFile.getBytes(), exeName);
            //拼接文件的访问路径并返回到前端页面
            String filePath = server_url + fileId;
            return new Result(true, filePath);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "上传失败!");
        }
    }
}

第四步:在SpringMVC中添加文件解析器的配置

<!-- 配置文件上传解析器 -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <property name="defaultEncoding" value="UTF-8"></property>
  <!-- 设定文件上传的最大值 5MB, 5*1024*1024 -->
  <property name="maxUploadSize" value="5242880"></property>
</bean>

第五步:页面文件上传的方法(这里是AngularJS)

//在前端service层中

app.service("uploadService",function ($http) {
    this.uploadFile=function () {
        var formData = new FormData();//上传文件的数据模型
        //第一个参数:相当于表单的name,第二个参数需和文件上传框的id一致
        formData.append("uploadFile",file.files[0]);
        return $http({
            method:'post',
            url:'../upload.do',
            data:formData,
            //文件上传,类型必须是undefined,因为默认是text/plain(有默认值angularJS就不处理了)
            headers:{'Content-type':undefined},
            transformRequest:angular.identity //对整个表单进行二进制序列化
        })
    }
})

附录:FastDFS的简单封装工具

/**
 * FastDFS使用的简单封装
 */
public class FastDFSClient {

  private TrackerClient trackerClient = null;
  private TrackerServer trackerServer = null;
  private StorageServer storageServer = null;
  private StorageClient1 storageClient = null;
  
  public FastDFSClient(String conf) throws Exception {
    if (conf.contains("classpath:")) {
      conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
    }
    ClientGlobal.init(conf);
    trackerClient = new TrackerClient();
    trackerServer = trackerClient.getConnection();
    storageServer = null;
    storageClient = new StorageClient1(trackerServer, storageServer);
  }
  
  /**
   * 上传文件方法
   * <p>Title: uploadFile</p>
   * <p>Description: </p>
   * @param fileName 文件全路径
   * @param extName 文件扩展名,不包含(.)
   * @param metas 文件扩展信息
   * @return
   * @throws Exception
   */
  public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
    String result = storageClient.upload_file1(fileName, extName, metas);
    return result;
  }
  
  public String uploadFile(String fileName) throws Exception {
    return uploadFile(fileName, null, null);
  }
  
  public String uploadFile(String fileName, String extName) throws Exception {
    return uploadFile(fileName, extName, null);
  }
  
  /**
   * 上传文件方法
   * <p>Title: uploadFile</p>
   * <p>Description: </p>
   * @param fileContent 文件的内容,字节数组
   * @param extName 文件扩展名
   * @param metas 文件扩展信息
   * @return
   * @throws Exception
   */
  public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
    
    String result = storageClient.upload_file1(fileContent, extName, metas);
    return result;
  }
  
  public String uploadFile(byte[] fileContent) throws Exception {
    return uploadFile(fileContent, null, null);
  }
  
  public String uploadFile(byte[] fileContent, String extName) throws Exception {
    return uploadFile(fileContent, extName, null);
  }
}

本文分享自微信公众号 - 顶哥说(DinTalk),作者:DinTalk

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Solr和Spring Data Solr

    Solr是一个开源搜索平台,用于构建搜索应用程序。 它建立在Lucene(全文搜索引擎)之上。 Solr是企业级的,快速的和高度可扩展的。Sol...

    宋先生
  • 词频统计小程序-WordCount.exe

    最近顶哥为了完成学历提升学业中的小作业,做了一个词频统计的.exe小程序。因为当时做的时候网上的比较少,因此顶哥决定把自己拙略的作品发出来给需要...

    宋先生
  • Java操作pdf: JarsperReport的简单使用

    在企业级应用开发中,报表生成、报表打印下载是其重要的一个环节。除了 Excel 报表之外,PDF 报表也有广泛的应用场景。

    宋先生
  • 实战技能:小小微信支付业务,何必虚惊一场

    记得上次接触微信支付是2016年底,那次也是我程序生涯中首次碰及支付业务,慌张谈不上但是懵逼怀疑时时都有。说起第三方登录或者支付,想必都清楚是直接调用人家现成的...

    赵小忠
  • 无回路有向图的拓扑排序

    因公司业务需要,在表单中每个字段都会配置自动计算,但自动计算公式中会引用到其他字段中的值。所以希望可以根据计算公式,优先计算引用的公式。所以最终使用了无回路有向...

    兜兜毛毛
  • 快递查询接口API/插件开发使用

      快递接口/插件是电商网站和系统商用来实现查询快递功能的主要方法,就类似淘宝京东查询物流轨迹一样,嵌入到自己系统里。

    用户6827397
  • Spring使用Filter添加自定义header

    十毛
  • nginx负载均衡(5种方式)、rewrite重写规则及多server反代配置梳理

    Nginx除了可以用作web服务器外,他还可以用来做高性能的反向代理服务器,它能提供稳定高效的负载均衡解决方案。nginx可以用轮询、IP哈希、URL哈希等方式...

    洗尽了浮华
  • CassandraAppender - distributed logging,分布式软件logback-appender

    农历年最后一场scala-meetup听刘颖分享专业软件开发经验,大受启发。突然意识到一直以来都没有完全按照任何标准的开发规范做事。诚然,在做技术调研和学...

    用户1150956
  • Java基础巩固计划

    3.26-4.1 JVM 虚拟机的内容写五篇博客 解决以下问题: 1. Java的内存模型以及GC算法 2. jvm性能调优都做了什么 3. 介绍JVM中7个区...

    Janti

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动