分布式文件服务器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 沒有實現自己的文件系統而是利用操作系統 的文件系統來管理文件??梢詫torage稱為存儲服務器。
服務端兩個角色:
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