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

 

一.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原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dintalk/p/11013254.html