1. 程式人生 > >SpringBoot2.0使用FastDFS實現上傳

SpringBoot2.0使用FastDFS實現上傳

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.上傳和下載流程

上傳

在這裡插入圖片描述

  1. Client通過Tracker server查詢可用的Storage server。
  2. Tracker server向Client返回一臺可用的Storage server的IP地址和埠號。
  3. Client直接通過Tracker server返回的IP地址和埠與其中一臺Storage server建立連線並進行檔案上傳。
  4. 上傳完成,Storage server返回Client一個檔案ID,檔案上傳結束。

下載

在這裡插入圖片描述

  1. Client通過Tracker server查詢要下載檔案所在的的Storage server。
  2. Tracker server向Client返回包含指定檔案的某個Storage server的IP地址和埠號。
  3. Client直接通過Tracker server返回的IP地址和埠與其中一臺Storage server建立連線並指定要下載檔案。
  4. 下載檔案成功。

4.安裝和使用

參考課前資料的:《centos安裝FastDFS.md

在這裡插入圖片描述

5.java客戶端

餘慶先生提供了一個Java客戶端,但是作為一個C程式設計師,寫的java程式碼可想而知。而且已經很久不維護了。

這裡推薦一個開源的FastDFS客戶端,支援最新的SpringBoot2.0。

配置使用極為簡單,支援連線池,支援自動生成縮圖,狂拽酷炫吊炸天啊,有木有。

地址:tobato/FastDFS_client

在這裡插入圖片描述

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;
        }
    }
}