FastDFS

分布式文件服务器FastDFS

1.FastDFS简介

        FastDFS 架构包括 Tracker server 和 Storage server。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。 Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。

FastDFS

服务端两个角色:

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

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

2.文件上传流程

FastDFS

客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

FastDFS

n 组名:文件上传后所在的 storage 组名称,在文件上传成功后有 storage 服务器返回,需要客户端自行保存。

n 虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项 store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。

n 数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。

n 文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

3. 文件下载流程

 

FastDFS

4 FastDFS安装

  略,安装比较麻烦。间配置文件

 

5.一般公共项目添加依赖

       <dependency>

        <groupId>org.csource.fastdfs</groupId>

        <artifactId>fastdfs</artifactId>

        </dependency>

        <dependency>

            <groupId>commons-fileupload</groupId>

            <artifactId>commons-fileupload</artifactId>

        </dependency>

6.公共项目添加FastDFSClient.java

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);

   }

}

7  配置文件。在需要用的项目添加配置。需要的项目依赖公共项目。

1. 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

 

2.配置 application.properties 文件。为文件上传的服务器地址

FILE_SERVER_URL=http://192.168.25.133/

 

3.spring中添加配置

 

<!-- 配置多媒体解析器 -->

   <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>

8.使用

@RestController

publicclass UploadController {

    @Value("${FILE_SERVER_URL}")

    private String FILE_SERVER_URL;//文件服务器地址

    @RequestMapping("/upload")

    public Result upload( MultipartFile file){             

        //1、取文件的扩展名

        String originalFilename = file.getOriginalFilename();

        String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);

        try {

           //2、创建一个 FastDFS 的客户端

            FastDFSClient fastDFSClient= new FastDFSClient("classpath:config/fdfs_client.conf");

            //3、执行上传处理

            String path = fastDFSClient.uploadFile(file.getBytes(), extName);

            //4、拼接返回的 urlip 地址,拼装成完整的 url

            String url = FILE_SERVER_URL + path;           

            return new Result(true,url);        

        } catch (Exception e) {

            e.printStackTrace();

            returnnew Result(false, "上传失败");

        }      

    }  

}

9.前端。使用了anjularjs

app.service("uploadService",function($http){

    this.uploadFile=function(){

        var formData=new FormData();

        formData.append("file",file.files[0]);  

        return $http({

            method:'POST',

            url:"../upload.do",

            data: formData,

            headers: {'Content-Type':undefined},

            transformRequest: angular.identity

        });    

    }  

});

 

html

<input type="file" id="file" />            

<button class="btn btn-primary" type="button"ng-click="uploadFile()">

anjularjs对于post和get请求默认的Content-Type header 是application/json。通过设置‘Content-Type’: undefined,这样浏览器会帮我们把Content-Type 设置为 multipart/form-data.

通过设置 transformRequest: angular.identity ,anjularjs transformRequest function 将序列化我们的formdata object.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

FormData的主要用途有两个:

1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。

(1).创建一个空的FormDate 使用append()添加

 var oMyForm = new FormData();

oMyForm.append("username", "Groucho");

oMyForm.append("file", $('#file')[0].files[0]);

(2) 绑定表单

 var formData = new FormData($('#uploadForm')[0]);

  formData.append('num', '1');//可以在已有表单数据的基础上,继续添加新的键值对

2、异步上传文件

enctype

 

    上面提到,form表单的默认值为‘application/x-www-form-urlencoded’, 而FormData的默认值为multipart/form-data,所以不用画蛇添足的去修改请求头.

 

    ①application/x-www-form-urlencode:表单提交的默认值,POST和GET对应的行为在上面已经讨论过,这里不再赘述;

 

    ②text/plain: 取这个值时,表单的值将不会进行编码,而是使用纯文本的方式提交到后台server,这个值基本没人用,因为在进行文件的提交时,不能提供对二进制数据的良好支持。

 

    ③multipart/form-data: 当enctype使用该选项时,浏览器将不会对字符进行编码,取而代之的是:以控件(input等)为单位进行分割,为每个控件加上Content-Disposition:form-data、name(input对应的name),filename(如果提交的是文件会有改字段),以及Content-Type(和上一个字段相同,提交文件时存在):文件类型(很容易伪造)。并且还会加上boundary(分隔符,不同浏览器不同,每次提交也不同)

 

var xhr = new XMLHttpRequest();

//使用FormData构造函数创建一个FormData的实例

var formData = new FormData();

// formData.append('file0', oInput.value);

//注意,这里的value不是普通的表单value,而是一个file对象

formData.append('file0', oInput.files[0]);

xhr.open('POST', 'http://localhost:8080');  

xhr.onload = function(){  

  if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {  

    console.log(xhr.responseText);  

  }  

};

//form表单的默认值为①,而FormData的默认值为multipart/form-data,所以不用画蛇添足的去修改请求头  

//xhr.setRequestHeader('Content-Type', 'multipart/form-data');

xhr.send(formData);  

上一篇:uni-app 图片上传(uploadFile)


下一篇:iview Upload组件多文件上传,以及vue文件下载