互聯網中有海量的文件,比如電商網站有海量的圖片文件,視頻網站有海量的視頻文件,如果使用傳統的模式上傳文件,肯定是不可取的。因此需要使用第三方服務器來存儲圖片 。
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上傳文件,我們以圖片的上傳為例(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>
# 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
/** * 圖片上傳的處理器 * @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, "上傳失敗!"); } } }
<!-- 配置文件上傳解析器 --> <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>
//在前端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使用的簡單封裝 */ 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); } }
關注微信公眾號,隨時隨地學習