代碼實作過程:
1.引入依賴,表示是FastDFS的用戶端
2.配置FastDFS配置檔案資訊,裡面包含了FastDFS的路徑、端口、連接配接逾時時間等(注意這個我并沒有加載,在使用的時候在工具類中加載這個檔案的,進而擷取Tracker對象)
3.SpringBoot配置檔案application.yml配置multipart設定上傳檔案大小
4.啟動類加入@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}):排除資料庫自動加載
5.已經搭建完成了
6.前端請求上傳,controller層使用Multipart接收,檔案的資訊封裝在裡面。
7.建立一個實體類FastDFSFile,使用者封裝Multipart中的資訊,例如檔案的名字、内容、字尾名等。然後然後調用工具類發方法把這個實體類傳入到工具類中,使用工具類上傳到伺服器中。傳回
8.工具類首先要加載fdfs_client.conf配置檔案,然後通過獲得實體類FastDFSFile中的資訊發送給服務。
9.工具類執行檔案上傳,會傳回字元串集合,然後傳回給controller層。
10.controller層再通過工具類擷取tracker 的ip和端口的資訊,然後和字元串拼接成完整的URL傳回給前端
1,簡介
簡單來說就是部署在伺服器中,然後把檔案上傳到改伺服器中的技術。是一個分布式系統。
需要安裝到docker上的。
FastDFS是一個開源的輕量級分布式檔案系統,它對檔案進行管理,功能包括:檔案存儲、檔案同步、檔案通路(檔案上傳、檔案下載下傳)等,解決了大容量存儲和負載均衡的問題。特别适合以檔案為載體的線上服務,如相冊網站、視訊網站等等。
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稱為存儲伺服器。
2,上傳流程
兩個元件:Tracker負責檔案管理負載均衡操作,控制中心(注冊中心)
Storage 檔案上傳、檔案下載下傳、檔案删除、檔案修改等…

storage Sever定時向Tracker Server注冊(Tracker Server更多是排程的作用)。
使用者請求上傳檔案請求Tracker,Tracker調用Storage查找可用的storage,tracker把查找到的storage傳回給用戶端(storage的IP和端口,作用就可以準确找到哪一個Storage Server),用戶端就根據IP和端口找到storage,用戶端上傳檔案的時候就會到這個Storager中,并且會在storage會建立升恒file_id并把上傳檔案内容寫入磁盤(伺服器中)。storage傳回資訊給用戶端,用戶端可以吧這些路徑資訊存到資料庫中。這樣我們就可以從資料庫中擷取路徑進而找到storage伺服器中檔案
注意,storage是以組的方式叢集
項目中的流程:檔案上傳到我們的項目,項目從tracker擷取storage傳回給項目,然後項目就把檔案上傳到storage就可以了。
用戶端上傳檔案後存儲伺服器将檔案 ID 傳回給用戶端,此檔案 ID 用于以後通路該檔案的索引資訊。檔案索引資訊包括:組名,虛拟磁盤路徑,資料兩級目錄,檔案名。
組名:檔案上傳後所在的 storage 組名稱,在檔案上傳成功後有storage 伺服器傳回,需要用戶端自行儲存。
虛拟磁盤路徑:storage 配置的虛拟路徑,與磁盤選項store_path*對應。如果配置了
store_path0 則是 M00,如果配置了 store_path1 則是 M01,以此類推。
資料兩級目錄:storage 伺服器在每個虛拟磁盤路徑下建立的兩級目錄,用于存儲資料
檔案。
檔案名:與檔案上傳時不同。是由存儲伺服器根據特定資訊生成,檔案名包含:源存儲
伺服器 IP 位址、檔案建立時間戳、檔案大小、随機數和檔案拓展名等資訊。
通路伺服器中的檔案是,是通過Nginx通路的。
3,檔案存儲微服務
預設FastDFS已經安裝好。
建立檔案管理微服務changgou-service-file,該工程主要用于實作檔案上傳以及檔案删除等功能。
3.1 依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>changgou-service</artifactId>
<groupId>com.changgou</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>changgou-service-file</artifactId>
<description>檔案上傳工程</description>
<!--依賴包-->
<dependencies>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
<dependency>
<groupId>com.changgou</groupId>
<artifactId>changgou-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
3.2 FastDFS配置
搭建上傳服務需要的配置檔案,其中端口和路徑是stacker的路徑,因為要先通過stacker才能擷取到storage
在resources檔案夾下建立fasfDFS的配置檔案fdfs_client.conf
connect_timeout=60
network_timeout=60
charset=UTF-8
http.tracker_http_port=8080
tracker_server=192.168.211.132:22122
connect_timeout:連接配接逾時時間,機關為秒。
network_timeout:通信逾時時間,機關為秒。發送或接收資料時。假設在逾時時間後還不能發送或接收資料,則本次網絡通信失敗
charset: 字元集
http.tracker_http_port :.tracker的http端口
tracker_server: tracker伺服器IP和端口設定
注意這裡是tracker的路徑,因為要先通過找到tracker才能擷取到storage
3.2 SpringBoot配置檔案
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
application:
name: file
server:
port: 18082
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
max-file-size是單個檔案大小,max-request-size是設定總上傳的資料大小
3.3 啟動類
建立com.changgou包,建立啟動類FileApplication
// 排除資料庫自動加載
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@EnableEurekaClient
public class FileApplication {
public static void main(String[] args) {
SpringApplication.run(FileApplication.class);
}
}
上傳檔案服務的啟動類需要加入@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
排除資料庫主動加載,因為該服務引用了changgou-common(裡面有加載資料庫的依賴)。如果不排除主動加載會報錯。
4,檔案上傳
操作過程:
前端點選上傳檔案背景是使用MultipartFile來接受,從MultipartFile中擷取裡面的資訊(包括檔案名等),把這些資訊封裝到FastDFSFile對象中,然後使用上傳工具類發檔案發送到伺服器中。把這些封裝資訊的對象傳入到工具類中就能可以實作上傳了,因為上傳的時候需要的就這這些資訊(檔案名,位元組類型,字尾名)。最後傳回URL給前端顯示。
4.1 檔案資訊封裝
檔案上傳一般都有檔案的名字、檔案的内容、檔案的擴充名、檔案的md5值、檔案的作者等相關屬性,我們可以建立一個對象封裝這些屬性,錄入上傳一張圖檔就需要這些資訊
代碼如下:
建立
com.changgou.file.FastDFSFile
代碼如下:
public class FastDFSFile implements Serializable {
//檔案名字
private String name;
//檔案内容
private byte[] content;
//檔案擴充名
private String ext;
//檔案MD5摘要值
private String md5;
//檔案建立作者
private String author;
public FastDFSFile(String name, byte[] content, String ext, String md5, String author) {
this.name = name;
this.content = content;
this.ext = ext;
this.md5 = md5;
this.author = author;
}
public FastDFSFile(String name, byte[] content, String ext) {
this.name = name;
this.content = content;
this.ext = ext;
}
public FastDFSFile() {
}
//..get..set..toString
}
4.2 controller檔案上傳
MultipartFile接受檔案上傳
建立一個FileController,在該控制器中實作檔案上傳操作,代碼如下:
@RestController
@CrossOrigin
public class FileController {
/***
* 檔案上傳
* @return
*/
@PostMapping(value = "/upload")
public String upload(@RequestParam("file")MultipartFile file) throws Exception {
//封裝一個FastDFSFile
FastDFSFile fastDFSFile = new FastDFSFile(
file.getOriginalFilename(), //檔案名字
file.getBytes(), //檔案位元組數組
StringUtils.getFilenameExtension(file.getOriginalFilename()));//檔案擴充名
//檔案上傳
String[] uploads = FastDFSClient.upload(fastDFSFile);
// 拼接通路位址
String url = FastDFSClient.getTrackerUrl()+"/"+uploads[0]+"/"+uploads[1];
//組裝檔案上傳位址
return new Result(true, StatusCode.OK, url);
}
}
4.2 檔案操作工具類
(1)初始化Tracker資訊
在
com.changgou.util.FastDFSClient
類中初始化Tracker資訊,在類中添加如下靜态塊:
就是要加載這個配置檔案
/***
* 初始化tracker資訊
*/
static {
try {
//擷取tracker的配置檔案fdfs_client.conf的位置
String filePath = new ClassPathResource("fdfs_client.conf").getPath();
//加載tracker配置資訊
ClientGlobal.init(filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
(2)操作檔案
方法中都會涉及到擷取TrackerServer或者StorageClient,我們可以把它們單獨抽取出去,分别在類中添加如下2個方法:
/***
* 擷取TrackerServer
*/
public static TrackerServer getTrackerServer() throws Exception{
//建立一個Tracker通路的用戶端對象TrackerClien
TrackerClient trackerClient = new TrackerClient();
//通過TrackerClient通路TrackerServer服務,擷取裡連接配接資訊
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
/***
* 擷取StorageClient
* @return
* @throws Exception
*/
public static StorageClient getStorageClient() throws Exception{
//擷取TrackerServer
TrackerServer trackerServer = getTrackerServer();
//通過TrackerServer建立StorageClient
StorageClient storageClient = new StorageClient(trackerServer,null);
return storageClient;
}
修改其他方法,在需要使用TrackerServer和StorageClient的時候,直接調用上面的方法,完整代碼如下:
public class FastDFSClient {
/***
* 初始化tracker資訊
*/
static {
try {
//擷取tracker的配置檔案fdfs_client.conf的位置
String filePath = new ClassPathResource("fdfs_client.conf").getPath();
//加載tracker配置資訊
ClientGlobal.init(filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
/****
* 檔案上傳
* @param file : 要上傳的檔案資訊封裝->FastDFSFile
* @return String[]
* 1:檔案上傳所存儲的組名
* 2:檔案存儲路徑
*/
public static String[] upload(FastDFSFile file){
//擷取檔案作者
NameValuePair[] meta_list = new NameValuePair[1];
meta_list[0] =new NameValuePair(file.getAuthor());
/***
* 檔案上傳後的傳回值
* uploadResults[0]:檔案上傳所存儲的組名,例如:group1
* uploadResults[1]:檔案存儲路徑,例如:M00/00/00/wKjThF0DBzaAP23MAAXz2mMp9oM26.jpeg
*/
String[] uploadResults = null;
try {
//擷取StorageClient對象
StorageClient storageClient = getStorageClient();
/**執行檔案上傳
*1 上傳檔案位元組數組
*2 檔案的字尾名
* 3 附加參數 例如拍攝場地:廣州
其中file.getExt在controller層就把字尾名加到FastDFSFile中了
*/
uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
} catch (Exception e) {
e.printStackTrace();
}
return uploadResults;
}
/***
* 擷取檔案資訊
* @param groupName:組名
* @param remoteFileName:檔案存儲完整名
*/
public static FileInfo getFile(String groupName,String remoteFileName){
try {
//擷取StorageClient對象
StorageClient storageClient = getStorageClient();
//擷取檔案資訊
return storageClient.get_file_info(groupName,remoteFileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 檔案下載下傳
* @param groupName:組名
* @param remoteFileName:檔案存儲完整名
* @return
*/
public static InputStream downFile(String groupName,String remoteFileName){
try {
//擷取StorageClient
StorageClient storageClient = getStorageClient();
//通過StorageClient下載下傳檔案
byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
//将位元組數組轉換成位元組輸入流
return new ByteArrayInputStream(fileByte);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 檔案删除實作
* @param groupName:組名
* @param remoteFileName:檔案存儲完整名
*/
public static void deleteFile(String groupName,String remoteFileName){
try {
//擷取StorageClient
StorageClient storageClient = getStorageClient();
//通過StorageClient删除檔案
storageClient.delete_file(groupName,remoteFileName);
} catch (Exception e) {
e.printStackTrace();
}
}
/***
* 擷取組資訊
* @param groupName :組名
*/
public static StorageServer getStorages(String groupName){
try {
//建立TrackerClient對象
TrackerClient trackerClient = new TrackerClient();
//通過TrackerClient擷取TrackerServer對象
TrackerServer trackerServer = trackerClient.getConnection();
//通過trackerClient擷取Storage組資訊
return trackerClient.getStoreStorage(trackerServer,groupName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 根據檔案組名和檔案存儲路徑擷取Storage服務的IP、端口資訊
* @param groupName :組名
* @param remoteFileName :檔案存儲完整名
*/
public static ServerInfo[] getServerInfo(String groupName, String remoteFileName){
try {
//建立TrackerClient對象
TrackerClient trackerClient = new TrackerClient();
//通過TrackerClient擷取TrackerServer對象
TrackerServer trackerServer = trackerClient.getConnection();
//擷取服務資訊
return trackerClient.getFetchStorages(trackerServer,groupName,remoteFileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/***
* 擷取Tracker服務位址
*/
public static String getTrackerUrl(){
try {
//建立TrackerClient對象
TrackerClient trackerClient = new TrackerClient();
//通過TrackerClient擷取TrackerServer對象
TrackerServer trackerServer = trackerClient.getConnection();
//擷取Tracker位址
return "http://"+trackerServer.getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/***
* 擷取TrackerServer
*/
public static TrackerServer getTrackerServer() throws Exception{
//建立TrackerClient對象
TrackerClient trackerClient = new TrackerClient();
//通過TrackerClient擷取TrackerServer對象
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
/***
* 擷取StorageClient
* @return
* @throws Exception
*/
public static StorageClient getStorageClient() throws Exception{
//擷取TrackerServer
TrackerServer trackerServer = getTrackerServer();
//通過TrackerServer建立StorageClient
StorageClient storageClient = new StorageClient(trackerServer,null);
return storageClient;
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-Bv6fN8Ak-1596182843330)(C:\Users\MT\AppData\Local\Temp\1596182789950.png)]
etConnection();
return trackerServer;
}
/***
* 擷取StorageClient
* @return
* @throws Exception
*/
public static StorageClient getStorageClient() throws Exception{
//擷取TrackerServer
TrackerServer trackerServer = getTrackerServer();
//通過TrackerServer建立StorageClient
StorageClient storageClient = new StorageClient(trackerServer,null);
return storageClient;
}
}
![\[外鍊圖檔轉存中...(img-Bv6fN8Ak-1596182843330)\]](https://img-blog.csdnimg.cn/20200731171810188.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODUwODcy,size_16,color_FFFFFF,t_70)