【FastDFS】SpringBoot整合FastDFS實戰,我只看這一篇!!

冰河團隊發表於2020-09-29

寫在前面

在《【FastDFS】小夥伴們說在CentOS 8伺服器上搭建FastDFS環境總報錯?》和《【FastDFS】面試官:如何實現檔案的大規模分散式儲存?(全程實戰)》文章中,我們詳細的搭建了FastDFS環境。那麼,現在環境是有了,如何將FastDFS整合到專案中呢?今天,我們就一起來聊聊這個問題。

注:工程原始碼已提交到:https://github.com/sunshinelyz/mykit-fastdfs

編譯Java客戶端

在FastDFS的官方Github上,專門有一個FastDFS Java客戶端的專案,連結地址為:https://github.com/happyfish100/fastdfs-client-java

我們將Java客戶端程式碼下載的本地,然後進入專案的目錄,使用Maven進行編譯,如下所示。

git clone https://github.com/happyfish100/fastdfs-client-java.git
cd fastdfs-client-java
mvn clean install -Dmaven.test.skip=true 

接下來,我們需要將FastDFS的Java客戶端編譯安裝到本地的Maven倉庫。

mvn install:install-file -DgroupId=com.fastdfs -DartifactId=fastdfs-client-java -Dversion=1.29 -Dpackaging=jar -Dfile=fastdfs-client-java-1.29-SNAPSHOT.jar

到此,我們就在本地編譯安裝了FastDFS的Java客戶端。

搭建專案

編輯pom.xml檔案

我們在IDEA中建立一個Maven專案,並在pom.xml檔案中引入SpringBoot相關依賴和我們自己編譯的FastDFS的Java客戶端。最終,pom.xml檔案的依賴如下所示。

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <skip_maven_deploy>false</skip_maven_deploy>
    <java.version>1.8</java.version>
    <logback.version>1.1.7</logback.version>
    <slf4j.version>1.7.21</slf4j.version>
    <common.logging>1.2</common.logging>
    <fastjson.version>1.2.51</fastjson.version>
    <fastdfs.client.version>1.29</fastdfs.client.version>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>${common.logging}</version>
    </dependency>

    <!-- log -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>${fastjson.version}</version>
    </dependency>

    <dependency>
        <groupId>com.fastdfs</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>${fastdfs.client.version}</version>
    </dependency>
</dependencies>

建立配置檔案

(1)在專案的src/main/resources目錄下建立SpringBoot的配置檔案application.yml,檔案內容如下所示。

server:
  port: 9999
  servlet:
    context-path: /resource
  tomcat:
    uri-encoding: UTF-8
      
spring:
  servlet:
    multipart:
      max-file-size: 1024MB
      max-request-size: 1024MB
  main:
    allow-bean-definition-overriding: true
  profiles:
    include: test
    active: test
  output:
    ansi:
      enabled: detect

檔案指定了專案啟動後監聽的埠,訪問的根路徑、專案編碼、檔案上傳的大小,並指定了執行時的環境。

(2)在專案的src/main/resources目錄下建立logback-spring.xml日誌檔案,具體配置見原始碼工程。

(3)在專案的src/main/resources目錄下建立fastdfs_client.conf檔案,主要用來配置與FastDFS的連線資訊。

connect_timeout = 200
network_timeout = 3000
charset = UTF-8
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
tracker_server = 192.168.175.100:22122

至此,專案搭建完成。接下來,我們就一起實現專案的功能。

專案開發

建立工具類

首先,我們在專案的io.mykit.fastdfs.utils包下建立FastDFSClientUtils工具類。這裡,我給出工具類的核心實現,其他部分小夥伴們參加原始碼工程。

/**
 * @author binghe
 * @description FastDFS分散式檔案系統操作客戶端
 */
public class FastDFSClientUtils {

    private static Logger logger = LoggerFactory.getLogger(FastDFSClientUtils.class);

    private static TrackerClient trackerClient;

    public static void setFile(String filePath) {
        try {
            logger.info("初始化分散式檔案系統服務開始...");
            if(filePath == null || filePath.trim().isEmpty()) {
                filePath = "fastdfs_client.conf";
            }
            ClientGlobal.init(filePath);
            TrackerGroup trackerGroup = ClientGlobal.g_tracker_group;
            trackerClient = new TrackerClient(trackerGroup);
            logger.info("初始化分散式檔案系統服務完成...");
        } catch (Exception e) {
            logger.error("載入檔案異常:{}",e );
        }
    }

    /**
     * @param data 資料
     * @param extName 副檔名
     * @return 上傳成功返回id,失敗返回null
     */
    public static String upload(byte[] data, String extName) {
        TrackerServer trackerServer = null;
        StorageServer storageServer = null;
        StorageClient1 storageClient1 = null;
        try {
            NameValuePair[] meta_list = null; // new NameValuePair[0];

            trackerServer = trackerClient.getTrackerServer();
            if (trackerServer == null) {
                logger.error("getConnection return null");
            }
            storageServer = trackerClient.getStoreStorage(trackerServer);
            storageClient1 = new StorageClient1(trackerServer, storageServer);
            String fileid = storageClient1.upload_file1(data, extName, meta_list);
            return fileid;
        } catch (Exception ex) {
            logger.error("上傳檔案異常:{}", ex);
            return null;
        }finally{
            try {
                storageClient1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            storageClient1 = null;
        }
    }

建立返回實體類

我們在io.mykit.fastdfs.bean包下建立ResourceBean類,用於SpringBoot介面返回結果資料,如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 上傳圖片後的返回資料
 */
public class ResourceBean implements Serializable {
	private static final long serialVersionUID = -2788538880352897307L;
	
	/**
	 * 檔案的訪問路徑
	 */
	private String fileUrl;
	
	/**
	 * 檔名稱
	 */
	private String fileName;
	
	public ResourceBean() {
		super();
	}

	public ResourceBean(String fileUrl, String fileName) {
		super();
		this.fileUrl = fileUrl;
		this.fileName = fileName;
	}

	public String getFileUrl() {
		return fileUrl;
	}

	public void setFileUrl(String fileUrl) {
		this.fileUrl = fileUrl;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	
}

其中,定義了檔案的訪問路徑fileUrl和檔案的名稱fileName。也就是說,檔案上傳成功後,我們會向客戶端返回檔案的訪問路徑和檔案的名稱資訊。

建立常量類

在io.mykit.fastdfs.constants包下建立ResourcesConstants常量類,ResourcesConstants類中主要定義了訪問檔案的基礎路徑和獲取檔案完整訪問路徑的方法,如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 常量
 */
public class ResourcesConstants {
	private static final String BASE_RESOURCES_URL = "http://192.168.175.100/";
	public static String getResourcesUrl(String fileId) {
		return BASE_RESOURCES_URL.concat(fileId);
	}
}

建立Controller類

在專案的io.mykit.fastdfs.controller包下建立ResourceController類,用於定義檔案上傳的介面。這個類的功能也比較簡單,就是定義一個檔案上傳介面,接收檔案,並呼叫FastDFSClientUtils工具類的upload(byte[], String)方法,將檔案上傳到FastDFS中,如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 上傳檔案介面
 */
@RestController
@RequestMapping(value = "/resources/")
public class ResourceController {

	@RequestMapping(value={"/upload"}, method=RequestMethod.POST)
	@ResponseBody
	public ResourceBean upload(@RequestParam("file") MultipartFile file, HttpServletRequest request, HttpServletResponse response){
		String extName = "";
		String fileName = "";
		String originalFilename = file.getOriginalFilename();
		if(originalFilename.contains(".")) {
			//拆分檔案路徑
			String[] fileArray = originalFilename.split("\\.");
			//獲取副檔名
			extName = fileArray[1];
			//獲取檔名
			fileName = fileArray[0];
		}else {
			fileName = originalFilename;
		}
		byte[] bytes = null;
		try {
			bytes = file.getBytes(); //將檔案轉換成位元組流形式
		} catch (IOException e) {
			e.printStackTrace();
		}
		//呼叫上傳檔案的具體方法
		String fileId= FastDFSClientUtils.upload(bytes,extName);
		return new ResourceBean(ResourcesConstants.getResourcesUrl(fileId), fileName);
	} 
}

建立啟動類

在專案的io.mykit.fastdfs包下,建立專案啟動類ResourceStarter,如下所示。

/**
 * @author binghe
 * @version 1.0.0
 * @description 啟動
 */
@SpringBootApplication
public class ResourceStarter {
	public static void main(String[] args) {
		try {
			String filePath = "fastdfs_client.conf";
			if(args.length > 0) {
				filePath = args[0];
			}
			FastDFSClientUtils.setFile(filePath);
			SpringApplication.run(ResourceStarter.class, args);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

從程式碼可以看出,ResourceStarter啟動類的main方法中,為filePath變數定義了一個預設的檔案路徑為fastdfs_client.conf,當啟動專案時,為main()方法傳遞了引數,則會使用第一個引數覆蓋掉filePath預設的值,並呼叫FastDFSClientUtils類的setFile()方法將filePath傳遞到FastDFSClientUtils類中進行初始化操作。

建立html檔案

最後,我們需要建立一個index.html檔案,用於測試檔案上傳操作。index.html檔案的內容也比較簡單,如下所示。

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"> 
	<title>檔案上傳和下載</title>
</head>
<body>
<form action='http://192.168.175.100:9999/resource/resources/upload' method='post' enctype='multipart/form-data'>
	<input type='file' name='file'>
	<button type='submit'>上傳</button>
</form>
</body>
</html>

至此,我們整個專案就開發完成了。

專案測試

首先,我們在IDEA中將mykit-fastdfs專案打包成mykit-fastdfs.jar檔案,然後將mykit-fastdfs.jar檔案上傳到伺服器的/usr/local/java目錄下,同時,我們將專案的src/main/resources目錄下的fastdfs_client.conf檔案,複製一份到伺服器的/usr/local/java目錄下。

在伺服器命令列輸入如下命令啟動mykit-fastdfs.jar。

nohup java -jar /usr/local/java/mykit-fastdfs.jar /usr/local/java/fastdfs_client.conf >> /dev/null &

接下來,我們將index.html檔案放到Nginx安裝目錄下的html/test目錄下。此時,在瀏覽器位址列中輸入http://192.168.175.100/test/index.html就能夠開啟頁面。

我們通過index.html頁面將檔案上傳到FastDFS檔案系統之後,瀏覽器中會顯示返回的結果資料,一個是檔案的訪問路徑fileUrl,一個是檔案的名稱fileName,如下所示。

{
    "fileUrl": "http://192.168.175.100/group1/M00/00/00/Ch8FQl9wfkSASTnYAACSPnJ7giA366.jpg",
    "fileName": "QQ截圖20200609234534"
}

具體如下圖所示。

我們開啟fileUrl標識的檔案訪問路徑,http://192.168.175.100/group1/M00/00/00/Ch8FQl9wfkSASTnYAACSPnJ7giA366.jpg,如下所示。


可以看到,瀏覽器能夠正確顯示上傳的圖片,說明我們已經在專案中成功整合了FastDFS的Java客戶端。

重磅福利

微信搜一搜【冰河技術】微信公眾號,關注這個有深度的程式設計師,每天閱讀超硬核技術乾貨,公眾號內回覆【PDF】有我準備的一線大廠面試資料和我原創的超硬核PDF技術文件,以及我為大家精心準備的多套簡歷模板(不斷更新中),希望大家都能找到心儀的工作,學習是一條時而鬱鬱寡歡,時而開懷大笑的路,加油。如果你通過努力成功進入到了心儀的公司,一定不要懈怠放鬆,職場成長和新技術學習一樣,不進則退。如果有幸我們江湖再見!

另外,我開源的各個PDF,後續我都會持續更新和維護,感謝大家長期以來對冰河的支援!!

寫在最後

如果你覺得冰河寫的還不錯,請微信搜尋並關注「 冰河技術 」微信公眾號,跟冰河學習高併發、分散式、微服務、大資料、網際網路和雲原生技術,「 冰河技術 」微信公眾號更新了大量技術專題,每一篇技術文章乾貨滿滿!不少讀者已經通過閱讀「 冰河技術 」微信公眾號文章,吊打面試官,成功跳槽到大廠;也有不少讀者實現了技術上的飛躍,成為公司的技術骨幹!如果你也想像他們一樣提升自己的能力,實現技術能力的飛躍,進大廠,升職加薪,那就關注「 冰河技術 」微信公眾號吧,每天更新超硬核技術乾貨,讓你對如何提升技術能力不再迷茫!

相關文章