SpringBoot(FastDFS文件上传)

FastDFS 相关概念

FastDFS 服务端有三个⻆色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)。
Tracker Server: 跟踪服务器,主要做调度工作,起负载均衡的作⽤用。在内存记录集群中所有存储组和存储服务器的状态信息,是客户端和数据服务器交互的枢纽。相⽐ GFS 中的 Master 更为精简,不记录文件索引信息,占用的内存量很少。

Storage Server: 存储服务器(⼜称存储节点或数据服务器),文件和⽂件属性(Meta Data)都保存到存储服务器上。Storage Server 直接利用 OS 的文件系统调⽤管理文件。

Client: 客户端,作为业务请求的发起方,通过专有接口,使用TCP/IP 协议与跟踪器服务器或存储节点进行数据交互。FastDFS 向使用者提供基本文件访问接⼝,如 upload、download、append、delete等,以客户端库的⽅式提供给用户使用。

pom 包配置:

<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27-SNAPSHOT</version>
</dependency>

FastDFS 配置
项目 resources 目录下添加 fdfs_client.conf ⽂件:

connect_timeout = 60 # 连接超时时间
network_timeout = 60 # ⽹网络超时时间
charset = UTF-8 # 编码格式
http.tracker_http_port = 8080 #tracker 端⼝口
http.anti_steal_token = no #token 防盗链功能
http.secret_key = 123456 #密钥
# tracer server 列列表,多个 tracer server 的话,分⾏行行列列出
tracker_server = 192.168.53.85:22122
tracker_server = 192.168.53.86:22122

封装 FastDFS 上传⼯具类
封装 FastDFSFile,⽂件基础信息包括文件名、内容、⽂件类型、作者等

public class FastDFSFile {
private String name;
private byte[] content;
private String ext;
private String md5;
private String author;
//省略略getter、setter
}

⾸先在类加载的时候读取配置信息,并进行初始化。
使用 FastDFS 提供的客户端 storageClient 来进行文件上传,最后将上传结果返回。

static {
try {
String filePath = new ClassPathResource("fdfs_client.conf").getFile().getA
bsolutePath();;
ClientGlobal.init(filePath);
} catch (Exception e) {
logger.error("FastDFS Client Init Fail!",e);
}
}

ClientGlobal.init 方法会读取配置文件,并初始化对应的属性。

1.⽂文件上传

public static String[] upload(FastDFSFile file) {
logger.info("File Name: " + file.getName() + "File Length:" + file.getContent(
).length);
//⽂文件属性信息
NameValuePair[] meta_list = new NameValuePair[1];
meta_list[0] = new NameValuePair("author", file.getAuthor());
long startTime = System.currentTimeMillis();
String[] uploadResults = null;
StorageClient storageClient=null;
try {
//获取
storageClient = getStorageClient();
//上传
uploadResults = storageClient.upload_file(file.getContent(), file.getExt()
, meta_list);
} catch (IOException e) {
logger.error("IO Exception when uploadind the file:" + file.getName(), e);
} catch (Exception e) {
logger.error("Non IO Exception when uploadind the file:" + file.getName(),
e);
}
logger.info("upload_file time used:" + (System.currentTimeMillis() - startTime
) + " ms");
//验证上传结果
if (uploadResults == null && storageClient!=null) {
logger.error("upload file fail, error code:" + storageClient.getErrorCode(
));
}
//上传⽂文件成功会返回 groupName。
logger.info("upload file successfully!!!" + "group_name:" + uploadResults[0] +
", remoteFileName:" + " " + uploadResults[1]);
return uploadResults;
}

NameValuePair,主要存储文件的一些基础属性,如作者信息、创建时间等;
getStorageClient(),封装了获取客户端的⽅法。

客户端实例例 StorageClient

private static StorageClient getStorageClient() throws IOException {
TrackerServer trackerServer = getTrackerServer();
StorageClient storageClient = new StorageClient(trackerServer, null);
return storageClient;
}

封装获取 TrackerServer 的⽅方法:

private static TrackerServer getTrackerServer() throws IOException {
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
return trackerServer;
}

2.获取⽂件
根据 groupName 和⽂件名获取文件信息。group 也可称为卷,同组内服务器上的文件是完全相同的,同一组内的 storage server 之间是对等的,⽂件上传、删除等操作可以在任意一台 storage server 上进⾏。

public static FileInfo getFile(String groupName, String remoteFileName) {
try {
storageClient = new StorageClient(trackerServer, storageServer);
return storageClient.get_file_info(groupName, remoteFileName);
} catch (IOException e) {
logger.error("IO Exception: Get File from Fast DFS failed", e);
} catch (Exception e) {
logger.error("Non IO Exception: Get File from Fast DFS failed", e);
}
return null;
}

3.下载⽂件
根据 storageClient 的 API 获取文件的字节流并返回:

public static InputStream downFile(String groupName, String remoteFileName) {
try {
StorageClient storageClient = getStorageClient();
byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
InputStream ins = new ByteArrayInputStream(fileByte);
return ins;
} catch (IOException e) {
logger.error("IO Exception: Get File from Fast DFS failed", e);
} catch (Exception e) {
logger.error("Non IO Exception: Get File from Fast DFS failed", e);
}
return null;
}

4.删除文件
根据文件名和组删除对应的⽂件

public static void deleteFile(String groupName, String remoteFileName)
throws Exception {
StorageClient storageClient = getStorageClient();
int i = storageClient.delete_file(groupName, remoteFileName);
logger.info("delete file successfully!!!" + i);
}

当使用 FastDFS 时,直接调用 FastDFSClient 对应的方法即可。

编写上传控制类
MultipartFile 中读取⽂件信息,然后使⽤用FastDFSClient 将文件上传到 FastDFS 集群中,封装一个saveFile() 方法⽤来调⽤上面封装的 FastDFS ⼯具类,将 MultipartFile 文件上传到 FastDFS 中,并返回上传后⽂件的地址信息。

public String saveFile(MultipartFile multipartFile) throws IOException {
String[] fileAbsolutePath={};
String fileName=multipartFile.getOriginalFilename();
String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
byte[] file_buff = null;
InputStream inputStream=multipartFile.getInputStream();
if(inputStream!=null){
int len1 = inputStream.available();
file_buff = new byte[len1];
inputStream.read(file_buff);
}
inputStream.close();
FastDFSFile file = new FastDFSFile(fileName, file_buff, ext);
try {
fileAbsolutePath = FastDFSClient.upload(file); //upload to fastdfs
} catch (Exception e) {
logger.error("upload file Exception!",e);
}
if (fileAbsolutePath==null) {
logger.error("upload file failed,please upload again!");
}
String path=FastDFSClient.getTrackerUrl()+fileAbsolutePath[0]+ "/"+fileAbsolut
ePath[1];
return path;
}

当上传请求传递到后端时,调⽤上面⽅法 saveFile()

@PostMapping("/upload")
public String singleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to u
pload");
return "redirect:uploadStatus";
}
try {
String path=saveFile(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + file.getOriginalFilename() + "'");
redirectAttributes.addFlashAttribute("path","file path url '" + path + "'"
);
} catch (Exception e) {
logger.error("upload file failed",e);
}
return "redirect:/uploadStatus";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值