FastDFS—分佈式文件存儲
1. 什麼是FastDFS
FastDFS是一個開源的輕量級分佈式文件系統,它對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。
2. FastDFS 的組成
- FastDFS 架構包括 Tracker server 和 Storage server。
客戶端請求 Tracker server 進行文件上傳、下載,通過Tracker server 調度最終由 Storage server 完成文件上傳和下載。
-
Tracker server 作用是負載均衡和調度,通過 Tracker server 在文件上傳時可以根據一些策略找到Storage server 提供文件上傳服務。可以將 tracker 稱爲追蹤服務器或調度服務器。
-
Storage server 作用是文件存儲,客戶端上傳的文件最終存儲在 Storage 服務器上,Storageserver 沒有實現自己的文件系統而是利用操作系統的文件系統來管理文件。可以將storage稱爲存儲服務器。
3. 搭建FastDFS文件存儲微服務
- 引入依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs‐client‐java</artifactId>
<version>1.27.0.0</version>
</dependency>
</dependencies>
- 在resources文件夾下創建fasfDFS的配置文件fdfs_client.conf
connect_timeout = 60 # 連接超時時間,單位爲秒。
network_timeout = 60 # 通信超時時間,單位爲秒。
charset = UTF‐8 # 字符集
http.tracker_http_port = 8080 # tracker的http端口
tracker_server = 192.168.200.128:22122 # tracker服務器IP和端口設置
- 在resources文件夾下創建application.yml
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
application:
name: file
server:
port: 9008
- 創建啓動類FileApplication
@SpringBootApplication
public class FileApplication {
public static void main(String[] args) {
SpringApplication.run(FileApplication.class);
}
}
- 準備一個封裝文件的實體類
package com.xm.file.pojo;
/**
* @title: FileApplication
* @projectName: changgou-parent
* @description: TODO
* @author: Zack_Tzh
* @date: 2019/12/8 14:15
*/
public class FastDFSFile {
//文件名字
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 height,
String width, String author) {
super();
this.name = name;
this.content = content;
this.ext = ext;
this.author = author;
}
public FastDFSFile(String name, byte[] content, String ext) {
super();
this.name = name;
this.content = content;
this.ext = ext;
}
// set get 。。。
- FastDFS工具類:FastDFSClient類
package com.xm.file.util;
import com.xm.file.pojo.FastDFSFile;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @title: FileApplication
* @projectName: changgou-parent
* @description: TODO
* @author: Zack_Tzh
* @date: 2019/12/8 15:15
*/
public class FastDFSClient {
private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
/***
* 初始化加載FastDFS的TrackerServer配置
*/
static {
try {
String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();
ClientGlobal.init(filePath);
} catch (Exception e) {
logger.error("FastDFS Client Init Fail!",e);
}
}
/***
* 文件上傳
* @param file
* @return
*/
public static String[] upload(FastDFSFile file) {
//獲取文件的作者
NameValuePair[] meta_list = new NameValuePair[1];
meta_list[0] = new NameValuePair("author", file.getAuthor());
//接收返回數據
String[] uploadResults = null;
StorageClient storageClient=null;
try {
//創建StorageClient客戶端對象
storageClient = getTrackerClient();
/***
* 文件上傳
* 1)文件字節數組
* 2)文件擴展名
* 3)文件作者
*/
uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
} catch (Exception e) {
logger.error("Exception when uploadind the file:" + file.getName(), e);
}
if (uploadResults == null && storageClient!=null) {
logger.error("upload file fail, error code:" + storageClient.getErrorCode());
}
//獲取組名
String groupName = uploadResults[0];
//獲取文件存儲路徑
String remoteFileName = uploadResults[1];
return uploadResults;
}
/***
* 獲取文件信息
* @param groupName:組名
* @param remoteFileName:文件存儲完整名
* @return
*/
public static FileInfo getFile(String groupName, String remoteFileName) {
try {
StorageClient storageClient = getTrackerClient();
return storageClient.get_file_info(groupName, remoteFileName);
} catch (Exception e) {
logger.error("Exception: Get File from Fast DFS failed", e);
}
return null;
}
/***
* 文件下載
* @param groupName
* @param remoteFileName
* @return
*/
public static InputStream downFile(String groupName, String remoteFileName) {
try {
//創建StorageClient
StorageClient storageClient = getTrackerClient();
//下載文件
byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
InputStream ins = new ByteArrayInputStream(fileByte);
return ins;
} catch (Exception e) {
logger.error("Exception: Get File from Fast DFS failed", e);
}
return null;
}
/***
* 文件刪除
* @param groupName
* @param remoteFileName
* @throws Exception
*/
public static void deleteFile(String groupName, String remoteFileName) throws Exception {
//創建StorageClient
StorageClient storageClient = getTrackerClient();
//刪除文件
int i = storageClient.delete_file(groupName, remoteFileName);
}
/***
* 獲取Storage組
* @param groupName
* @return
* @throws IOException
*/
public static StorageServer[] getStoreStorages(String groupName) throws IOException {
//創建TrackerClient
TrackerClient trackerClient = new TrackerClient();
//獲取TrackerServer
TrackerServer trackerServer = trackerClient.getConnection();
//獲取Storage組
return trackerClient.getStoreStorages(trackerServer, groupName);
}
/***
* 獲取Storage信息,IP和端口
* @param groupName
* @param remoteFileName
* @return
* @throws IOException
*/
public static ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
}
/***
* 獲取Tracker服務地址
* @return
* @throws IOException
*/
public static String getTrackerUrl() throws IOException {
return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/";
}
/***
* 獲取Storage客戶端
* @return
* @throws IOException
*/
private static StorageClient getTrackerClient() throws IOException {
TrackerServer trackerServer = getTrackerServer();
StorageClient storageClient = new StorageClient(trackerServer, null);
return storageClient;
}
/***
* 獲取Tracker
* @return
* @throws IOException
*/
private static TrackerServer getTrackerServer() throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}
}
- 創建Controller接收文件並上傳到FastDFS上
package com.xm.file.controller;
import com.xm.file.pojo.FastDFSFile;
import com.xm.file.util.FastDFSClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* @title: FileController
* @projectName: changgou-parent
* @description: TODO
* @author: Zack_Tzh
* @date: 2019/12/8 18:45
*/
@RestController
@RequestMapping("/xm/v1/file")
public class FileController {
@RequestMapping("/upload")
public String upload(MultipartFile file) {
try {
//獲取原始文件名
String originalFilename = file.getOriginalFilename();
//獲取文件後綴
String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
//文件數據
byte[] data = file.getBytes();
//創建文件上傳的封裝實體類
FastDFSFile fastDFSFile = new FastDFSFile(originalFilename, data, ext);
//用FastDFSClient工具類上傳文件
String[] uploadResults = FastDFSClient.upload(fastDFSFile);
//拼接文件訪問地址
String url = FastDFSClient.getTrackerUrl() + uploadResults[0] +"/"+ uploadResults[1];
System.out.println(url);
return url;
} catch (IOException e) {
e.printStackTrace();
return "文件上傳失敗";
}
}
}