SpringBoot2.0使用FastDFS實現上傳
阿新 • • 發佈:2019-01-13
1.什麼是分散式檔案系統
分散式檔案系統(Distributed File System)是指檔案系統管理的物理儲存資源不一定直接連線在本地節點上,而是通過計算機網路與節點相連。
通俗來講:
- 傳統檔案系統管理的檔案就儲存在本機。
- 分散式檔案系統管理的檔案儲存在很多機器,這些機器通過網路連線,要被統一管理。無論是上傳或者訪問檔案,都需要通過管理中心來訪問
2.什麼是FastDFS
FastDFS是由淘寶的餘慶先生所開發的一個輕量級、高效能的開源分散式檔案系統。用純C語言開發,功能豐富:
- 檔案儲存
- 檔案同步
- 檔案訪問(上傳、下載)
- 存取負載均衡
- 線上擴容
適合有大容量儲存需求的應用或系統。同類的分散式檔案系統有谷歌的GFS、HDFS(Hadoop)、TFS(淘寶)等。
3.FastDFS的架構
3.1.架構圖
先上圖:
FastDFS兩個主要的角色:Tracker Server 和 Storage Server 。
- Tracker Server:跟蹤伺服器,主要負責排程storage節點與client通訊,在訪問上起負載均衡的作用,和記錄storage節點的執行狀態,是連線client和storage節點的樞紐。
- Storage Server:儲存伺服器,儲存檔案和檔案的meta data(元資料),每個storage server會啟動一個單獨的執行緒主動向Tracker cluster中每個tracker server報告其狀態資訊,包括磁碟使用情況,檔案同步情況及檔案上傳下載次數統計等資訊
- Group:檔案組,多臺Storage Server的叢集。上傳一個檔案到同組內的一臺機器上後,FastDFS會將該檔案即時同步到同組內的其它所有機器上,起到備份的作用。不同組的伺服器,儲存的資料不同,而且相互獨立,不進行通訊。
- Tracker Cluster:跟蹤伺服器的叢集,有一組Tracker Server(跟蹤伺服器)組成。
- Storage Cluster :儲存叢集,有多個Group組成。
3.2.上傳和下載流程
上傳
- Client通過Tracker server查詢可用的Storage server。
- Tracker server向Client返回一臺可用的Storage server的IP地址和埠號。
- Client直接通過Tracker server返回的IP地址和埠與其中一臺Storage server建立連線並進行檔案上傳。
- 上傳完成,Storage server返回Client一個檔案ID,檔案上傳結束。
下載
- Client通過Tracker server查詢要下載檔案所在的的Storage server。
- Tracker server向Client返回包含指定檔案的某個Storage server的IP地址和埠號。
- Client直接通過Tracker server返回的IP地址和埠與其中一臺Storage server建立連線並指定要下載檔案。
- 下載檔案成功。
4.安裝和使用
參考課前資料的:《centos安裝FastDFS.md》
5.java客戶端
餘慶先生提供了一個Java客戶端,但是作為一個C程式設計師,寫的java程式碼可想而知。而且已經很久不維護了。
這裡推薦一個開源的FastDFS客戶端,支援最新的SpringBoot2.0。
配置使用極為簡單,支援連線池,支援自動生成縮圖,狂拽酷炫吊炸天啊,有木有。
5.1.引入依賴
在父工程中,我們已經管理了依賴,版本為:
<fastDFS.client.version>1.26.2</fastDFS.client.version>
因此,這裡我們直接引入座標即可:
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
5.2.引入配置類
純java配置:
@Configuration
@Import(FdfsClientConfig.class)
// 解決jmx重複註冊bean的問題
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {
}
5.3.編寫FastDFS屬性
fdfs:
so-timeout: 1501
connect-timeout: 601
thumb-image: # 縮圖
width: 60
height: 60
tracker-list: # tracker地址
- 192.168.56.101:22122 #伺服器ip
5.4.測試
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LyUploadService.class)
public class FdfsTest {
@Autowired
private FastFileStorageClient storageClient;
@Autowired
private ThumbImageConfig thumbImageConfig;
@Test
public void testUpload() throws FileNotFoundException {
File file = new File("D:\\test\\baby.png");
// 上傳並且生成縮圖
StorePath storePath = this.storageClient.uploadFile(
new FileInputStream(file), file.length(), "png", null);
// 帶分組的路徑
System.out.println(storePath.getFullPath());
// 不帶分組的路徑
System.out.println(storePath.getPath());
}
@Test
public void testUploadAndCreateThumb() throws FileNotFoundException {
File file = new File("D:\\test\\baby.png");
// 上傳並且生成縮圖
StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(
new FileInputStream(file), file.length(), "png", null);
// 帶分組的路徑
System.out.println(storePath.getFullPath());
// 不帶分組的路徑
System.out.println(storePath.getPath());
// 獲取縮圖路徑
String path = thumbImageConfig.getThumbImagePath(storePath.getPath());
System.out.println(path);
}
}
結果:
group1/M00/00/00/wKg4ZVro5eCAZEMVABfYcN8vzII630.png
M00/00/00/wKg4ZVro5eCAZEMVABfYcN8vzII630.png
M00/00/00/wKg4ZVro5eCAZEMVABfYcN8vzII630_60x60.png
訪問第一個路徑:
訪問最後一個路徑(縮圖路徑),注意加組名:
5.5.改造上傳邏輯
@Service
public class UploadService {
private static final Logger logger = LoggerFactory.getLogger(UploadController.class);
// 支援的檔案型別
private static final List<String> suffixes = Arrays.asList("image/png", "image/jpeg");
@Autowired
FastFileStorageClient storageClient;
public String upload(MultipartFile file) {
try {
// 1、圖片資訊校驗
// 1)校驗檔案型別
String type = file.getContentType();
if (!suffixes.contains(type)) {
logger.info("上傳失敗,檔案型別不匹配:{}", type);
return null;
}
// 2)校驗圖片內容
BufferedImage image = ImageIO.read(file.getInputStream());
if (image == null) {
logger.info("上傳失敗,檔案內容不符合要求");
return null;
}
// 2、將圖片上傳到FastDFS
// 2.1、獲取檔案字尾名
String extension = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
// 2.2、上傳
StorePath storePath = this.storageClient.uploadFile(
file.getInputStream(), file.getSize(), extension, null);
// 2.3、返回完整路徑
return "http://image.leyou.com/" + storePath.getFullPath();
} catch (Exception e) {
return null;
}
}
}