分布式文件服务器FastDFS
目录
1.什么是FastDFS
2.文件上传和下载流程
(1)文件上传流程
(2)文件下载流程
3.FastDFS图片上传及回显的案例
(1)导入pom依赖
(2)导入springmvc的配置和FastDFS的配置文件
(3)编写web.xml
(4)创建返回的结果对象
(5)导入FastDFSClient的工具类
(6)创建文件上传的Controller层代码
(7)前端anjularjs的代码,这里用MVC模式的编写方式
(8)编写文件上传的html代码
1.什么是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 分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。
2.文件上传和下载流程
(1)文件上传流程
客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。
组名:文件上传后所在的 storage 组名称,在文件上传成功后有 storage 服务器返回,需要客户端自行保存。
虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项 store_path*对应。如果配置了store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。
数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
(2)文件下载流程
3.FastDFS图片上传及回显的案例
-
这里我们用angularjs和SpringMVC实现文件上传及回显
-
文件的最终结构如下
-
该案例中用的是安装了FastDFS的虚拟机
(1)导入pom依赖
<dependencies><!-- json转换 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version></dependency><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><!-- SpringMVC --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.2.4.RELEASE</version></dependency></dependencies>(2)导入springmvc的配置和FastDFS的配置文件
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 默认使用基于注释的适配器和映射器 --><mvc:annotation-driven/> <!-- 只把动态信息当做controller处理,忽略静态信息 --><mvc:default-servlet-handler/> <!--FastJson配置 --><mvc:annotation-driven><mvc:message-converters register-defaults="true"><bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"><property name="supportedMediaTypes" value="application/json"/><property name="features"><array><value>WriteMapNullValue</value><value>WriteDateUseDateFormat</value></array></property></bean></mvc:message-converters></mvc:annotation-driven> <!-- 配置创建spring容器要扫描的包 --><context:component-scan base-package="controller"></context:component-scan> <!-- 配置多媒体解析器 --><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> </beans>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(3)编写web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"> <!-- 解决post乱码 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param><init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping> <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping> </web-app>(4)创建返回的结果对象
Result.java
public class Result implements Serializable{private boolean success;private String message; }(5)导入FastDFSClient的工具类
FastDFSClient.java
package util; import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; import org.csource.fastdfs.StorageClient1; import org.csource.fastdfs.StorageServer; import org.csource.fastdfs.TrackerClient; import org.csource.fastdfs.TrackerServer; 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);} }(6)创建文件上传的Controller层代码
UploadController.java
@RestController public class UploadController { @Value("http://192.168.25.133/")private String FILE_SERVER_URL; @RequestMapping("upload")public Result upload(MultipartFile file) {//获取图片的后缀名String filename = file.getOriginalFilename();System.out.println("filename"+filename);String extName = filename.substring(filename.lastIndexOf(".") + 1);System.out.println("extName:"+extName);try {FastDFSClient dfsClient = new FastDFSClient("classpath:fdfs_client.conf");//执行上传处理String path = dfsClient.uploadFile(file.getBytes(), extName);//拼接返回的 url 和 ip 地址,拼装成完整的 urlString url = FILE_SERVER_URL + path;System.out.println(url);return new Result(true, url);} catch (Exception e) {e.printStackTrace();return new Result(false, "上传失败");}} }(7)前端anjularjs的代码,这里用MVC模式的编写方式
base.js
var app=angular.module('myapp',[]);uploadService.js
app.service("uploadService", function ($http) {this.uploadFile = function() {var formData = new FormData(); //上传文件的数据模型formData.append("file", file.files[0]); //文件上传框的id必须是和append的第一个参数一致return $http({method : 'post',url : "/upload.do",data : formData,headers : {'Content-Type' : undefined}, //上传文件必须是这个类型,默认text/plaintransformRequest : angular.identity //对整个表单进行二进制序列化});} });uploadController.js
//控制层 app.controller('uploadController', function ($scope,uploadService) { //文件上传$scope.uploadFile = function () {uploadService.uploadFile().success(function (response) {if (response.success) {$scope.imageUrl = response.message;} else {alert(response.message);}}).error(function () {alert("上传发生错误");});} })(8)编写文件上传的html代码
upload.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>文件上传</title> </head> <!-- 导入angular的js文件 --> <script type="text/javascript" src="js/angular.min.js"> </script> <!-- 导入自定义的angular模块--> <script type="text/javascript" src="js/base.js"> </script> <script type="text/javascript" src="js/service/uploadService.js"> </script> <script type="text/javascript" src="js/controller/uploadController.js"> </script> <body ng-app="myapp" ng-controller="uploadController"> 图片上传:<input type="file" id="file"><br/><!-- 通过点击按钮实现异步调用uploadController的uploadFile()方法返回文件上传之后的路径,利用angular的双向绑定的特性使得图片回显到浏览器中 --> <img src="{{imageUrl}}" width="200px" height="200px"><br/> <input type="button" value="上传" ng-click="uploadFile()"> </body> </html>最终浏览器展示的效果如下:
总结
以上是生活随笔为你收集整理的分布式文件服务器FastDFS的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Spring-data-redis入门
- 下一篇: 消息中间体activeMQ