一、FastDFS文件系统简介
FastDFS源码: Github地址:https://github.com/happyfish100
搭建FastDFS:
参考地址:
https://blog.csdn.net/wlwlwlwl015/article/details/52619851
https://www.cnblogs.com/chiangchou/p/fastdfs.html
FastDFS 是一个开源的高性能分布式文件系统(DFS)。 它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载平衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。
FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)。
Tracker Server:跟踪服务器,主要做调度工作,起到均衡的作用;负责管理所有的 storage server和 group,每个 storage 在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。
Storage Server:存储服务器,主要提供容量和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份。
Client:客户端,上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。
更多关于FastDFS系统的相关知识,请自行查阅。
二、SpringBoot结合FastDFS实现文件上传功能
(1)项目工程目录结构
(2)项目pom.xml配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.26.1-RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> <version>2.1.1.RELEASE</version> </dependency> </dependencies>
(3)FDS配置文件: fdfs_client.conf:
#以下为你搭建的FastDFS系统的配置信息,请自行修改 connect_timeout = 60 network_timeout = 60 charset = UTF-8 http.tracker_http_port = 8080 http.anti_steal_token = no http.secret_key = 123456 tracker_server = 127.0.0.1:22122
(4)项目部分代码
后台:
(a)FasfDFSClient.java
package com.lhf.springbootfastdfs.fastdfs; import org.csource.common.NameValuePair; import org.csource.fastdfs.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import java.io.*; /** * @ClassName: FasfDFSClient * @Desc: FastDFS客户端 * @Author: liuhefei * @Date: 2018/12/24 17:33 */ public class FastDFSClient { private static Logger logger = LoggerFactory.getLogger(FastDFSClient.class); //在类加载的时候读取相应的配置信息,并进行初始化。 static{ try{ String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath(); ClientGlobal.init(filePath); }catch (Exception e){ logger.error("FastDFS Client Init Fail!",e); } } /** * 文件上传 * 使用FastDFS提供的客户端storageClient来进行文件上传,最后将上传结果返回。 * @param file * @return */ 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 = getTrackerClient(); 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()); } String groupName = uploadResults[0]; String remoteFileName = uploadResults[1]; logger.info("upload file successfully!!!" + "group_name:" + groupName + ", remoteFileName:" + " " + remoteFileName); return uploadResults; } /** * 根据groupName和文件名获取文件信息。 * @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 (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; } /** * 下载文件 * @param groupName * @param remoteFileName * @return */ public static InputStream downFile(String groupName, String remoteFileName) { try { StorageClient storageClient = getTrackerClient(); 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; } /** * 删除文件 * @param groupName * @param remoteFileName * @throws Exception */ public static void deleteFile(String groupName, String remoteFileName) throws Exception { StorageClient storageClient = getTrackerClient(); int i = storageClient.delete_file(groupName, remoteFileName); logger.info("delete file successfully!!!" + i); } public static StorageServer[] getStoreStorages(String groupName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getStoreStorages(trackerServer, groupName); } public static ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); } public static String getTrackerUrl() throws IOException { return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/"; } private static StorageClient getTrackerClient() throws IOException { TrackerServer trackerServer = getTrackerServer(); StorageClient storageClient = new StorageClient(trackerServer, null); return storageClient; } private static TrackerServer getTrackerServer() throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerServer; } }
(b)FastDFSFile.java
package com.lhf.springbootfastdfs.fastdfs; /** * @ClassName: FastDFSFile * @Desc: * @Author: liuhefei * @Date: 2018/12/24 17:33 */ public class FastDFSFile { private String name; private byte[] content; private String ext; 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; } public String getName() { return name; } public void setName(String name) { this.name = name; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; } public String getExt() { return ext; } public void setExt(String ext) { this.ext = ext; } public String getMd5() { return md5; } public void setMd5(String md5) { this.md5 = md5; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
(c)controller控制层UploadController.java:实现上传文件
package com.lhf.springbootfastdfs.controller; import com.lhf.springbootfastdfs.fastdfs.FastDFSClient; import com.lhf.springbootfastdfs.fastdfs.FastDFSFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import java.io.IOException; import java.io.InputStream; /** * @ClassName: UploadController * @Desc: * @Author: liuhefei * @Date: 2018/12/24 17:34 */ @Controller public class UploadController { private static Logger logger = LoggerFactory.getLogger(UploadController.class); @GetMapping("/") public String index(){ return "upload"; } @PostMapping("/upload") public String singleFileUpload(@RequestParam("file")MultipartFile file, RedirectAttributes redirectAttributes){ if(file.isEmpty()){ redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); 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"; } @GetMapping("/uploadStatus") public String uploadStatus(){ return "uploadStatus"; } /** * 保存文件 * 从MultipartFile中读取文件信息,然后使用FastDFSClient将文件上传到FastDFS集群中。 * @param multipartFile * @return * @throws IOException */ 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]+ "/"+fileAbsolutePath[1]; logger.info("path = {}", path); return path; } }
(d)前端页面:upload.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <body> <h1>Spring Boot file upload example</h1> <form method="POST" action="/upload" enctype="multipart/form-data"> <input type="file" name="file" /><br/><br/> <input type="submit" value="Submit" /> </form> </body> </html>
实例效果如图:
图片上传成功,通过返回的地址即可查看!
项目地址:https://github.com/JavaCodeMood/springboot-fastdfs
分享就到这里,感谢诸君的支持!