springBoot完美集成FastDFS
我们在日常开发中存储文件是很常见。市面上提供给我们的资源也很多。最简单的办法就是去买比如BAT的。但是随着项目的增大,数据的增多。集群、多数据源等只是解决了请求的接受分发。但是文件数据并没有的到很好的处理。
一介绍
什么是FastDFS
FastDFS是用c语言编写的一款开源的分布式文件系统。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
FastDFS提供的功能
• upload:上传普通文件,包括主文件 • upload_appender:上传appender文件,后续可 以对其进行append操作 • upload_slave:上传从文件 • download:下载文件 • delete:删除文件 • append:在已有文件后追加内容 • set_metadata:设置文件附加属性 • get_metadata:获取文件附加属性
FastDFS的特点
• 分组存储,灵活简洁 • 对等结构,不存在单点 • 文件ID由FastDFS生成,作为文件访问凭证。FastDFS 不需要传统的name server • 和流行的web server无缝衔接,FastDFS已提供 apache和nginx扩展模块 • 大、中、小文件均可以很好支持,支持海量小文件 存储 • 支持多块磁盘,支持单盘数据恢复 • 支持相同文件内容只保存一份,节省存储空间 • 存储服务器上可以保存文件附加属性 • 下载文件支持多线程方式,支持断点续传
以上是关于FastDFS简述,关于FastDFS的安装,集群小常子会在下一篇博客分享。
本次演示代码环境
jdk 1.8 Tomcat 8.0以上 springboot 2.0.2 fastDFs 5.0.5 nginx 1.8 centOS7.6 服务器连接工具 FinalShell
centOS安装:https://blog.csdn.net/qq_37922509/article/details/96869050
FinalShell介绍:https://blog.csdn.net/qq_37922509/article/details/96867278
其他安装教程,小常子努力编写中。。。
创建一个springBoot工程,后开始集成
下图红色框使我们接下来要用到的
### pom文件添加一下依赖
<!--fstdfs fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 文件服务器-->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.1-RELEASE</version>
</dependency>
编写类
FastDFSClientWrapper
package org.jeecg.modules.fastdfs;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 功能描述: 文件处理类
*
* @author 小常子
* @version V1.0
* @date 2019/7/31
*/
@Component
@Slf4j
public class FastDFSClientWrapper {
@Autowired
private FastFileStorageClient storageClient;
@Autowired
private FdfsConfig fdfsConfig;
public String uploadFile(MultipartFile file) throws IOException {
StorePath storePath = storageClient.uploadFile((InputStream) file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
log.info("storePath:" + storePath);
return getResAccessUrl(storePath);
}
/**
* 封装文件完整URL地址
*
* @param storePath
* @return
*/
private String getResAccessUrl(StorePath storePath) {
//GlobalConstants.HTTP_PRODOCOL +
String fileUrl = GlobalConstants.HTTP_FILEURL + ":" + fdfsConfig.getStoragePort() + "/" + storePath.getFullPath();
log.info("fileUrl:" + fileUrl);
return fileUrl;
}
/**
* 功能描述: 删除文件
*
* @param fileUrl
* @return void
* @author 小常子
* @date 2019/7/31
* @version V1.0
*/
public void deleteFile(String fileUrl) {
log.info("删除的文件的url:" + fileUrl);
if (StringUtils.isEmpty(fileUrl)) {
return;
}
try {
StorePath storePath = StorePath.praseFromUrl(fileUrl);
log.info("groupName:"+storePath.getGroup()+"------"+"文件路径path:"+storePath.getPath());
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (FdfsUnsupportStorePathException e) {
log.warn(e.getMessage());
}
}
/**
* 功能描述: 下载文件
*
* @param fileUrl
* @return java.io.InputStream
* @author 小常子
* @date 2019/7/31
* @version V1.0
*/
public InputStream downFile(String fileUrl) {
try {
StorePath storePath = StorePath.praseFromUrl(fileUrl);
byte[] fileByte = storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
InputStream ins = new ByteArrayInputStream(fileByte);
return ins;
} catch (Exception e) {
log.error("Non IO Exception: Get File from Fast DFS failed", e);
}
return null;
}
}
FdfsConfig
package org.jeecg.modules.fastdfs;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author: 小常子
* @Date: 2019/7/31
* @Description:
* @Modify By:
*/
@Component
public class FdfsConfig {
@Value("${fdfs.res-host}")
private String resHost;
@Value("${fdfs.storage-port}")
private String storagePort;
public String getResHost() {
return resHost;
}
public void setResHost(String resHost) {
this.resHost = resHost;
}
public String getStoragePort() {
return storagePort;
}
public void setStoragePort(String storagePort) {
this.storagePort = storagePort;
}
}
FdfsConfiguration
package org.jeecg.modules.fastdfs;
/**
* @Date: 2019/7/31
* @Description:
* @Modify By:
*/
import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FdfsConfiguration {
}
GlobalConstants
package org.jeecg.modules.fastdfs;
/**
* @author: 小常子
* @Date: 2019/7/31
* @Description:
* @Modify By:
*/
public class GlobalConstants {
public final static String HTTP_FILEURL = "http://47.101.209.242";
}
UploadController
package org.jeecg.modules.fastdfs;
import org.jeecg.modules.api.memberInfo.controller.MemberInfoController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
/**
* @author: 小常子
* @Date: 2019/7/31
* @Description:
* @Modify By:
*/
@Slf4j
@Api(tags="文件上传")
@RestController
@RequestMapping("/upload")
public class UploadController {
@Autowired
private FastDFSClientWrapper dfsClient;
@GetMapping("/")
public String index() {
return "upload/upload";
}
@PostMapping("/fdfs_upload")
public String fdfsUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
return "redirect:/upload/uploadStatus";
}
try {
String fileUrl = dfsClient.uploadFile(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + fileUrl + "'");
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/upload/uploadStatus";
}
@GetMapping("/uploadStatus")
public String uploadStatus() {
return "upload/uploadStatus";
}
@RequestMapping("/deleteFile")
@ResponseBody
public String deleteFile(@RequestParam(value = "fileUrl") String fileUrl) {
dfsClient.deleteFile(fileUrl);
return "Success";
}
}
以上是集成所需代码。测试大家可自己写一个freemarker也可自己写一个页面。
我用的是freemark
upload.ftl
<!DOCTYPE html>
<html>
<body>
<h1>Spring Boot file upload example</h1>
<form method="POST" action="fdfs_upload" enctype="multipart/form-data">
<input type="file" name="file" /><br/><br/>
<input type="submit" value="Submit" />
</form>
</body>
</html>
uploadStatus.ftl
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<h1>Spring Boot - Upload Status</h1>
<div>
<h1>${message}</h1>
</div>
</body>
</html>
配置文件引入freemark
配置好FastDFS
开始使用
注:以上如果是新建项目没有任何问题。如果是已成型项目,在测试是务必考虑权限问题。
如
到此,本次分享结束。希望能帮到你。