分布式文件系统解决方案续:Springboot集成FastDFS-分布式文件系统

分布式文件系统解决方案续:Springboot集成FastDFS-分布式文件系统

上一篇文章写了关于如何部署分布式文件系统FastDFS,在本篇文章中讲解如何在Spring boot中集成FastDFS。

加入依赖:

<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.4</version>
</dependency>

yml配置:

fdfs:
so-timeout: 1500 #socketsocket连接超时时长
connect-timeout: 600 #连接tracker服务器超时时长
thumb-image: #缩略图生成参数,可选
width: 150
height: 150
tracker-list: #TrackerList参数,支持多个,我这里只有一个,如果有多个在下方加- x.x.x.x:port
- 192.168.1.141:22122
imgHost: http://192.168.1.141 #图片访问路径前缀

增加配置类(此类里面什么都不需要做,也可以把@Import和@EnableMBeanExport放在启动类上,感觉启动类上放太多东西不好看就增加了一个配置类)

FdfsConfiguration.java

package com.qfkj.upload.config;
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)//注解,就可以拥有带有连接池的FastDFS Java客户端了
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FdfsConfiguration {
}

上传工具类封装

FastDFSUploadUtils.java

package com.qfkj.upload.utils;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.qfkj.upload.config.FdfsConfig;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
/**
* @author han
* create 2018-11-22
*/
@Component
public class FastDFSUploadUtils {
@Autowired
private FastFileStorageClient storageClient;
@Autowired
private ThumbImageConfig thumbImageConfig;
@Value("${fdfs.imgHost}")
private String imgHost;
/**
* 上传并返回全访问路径
* @param file
* @return
* @throws IOException
*/
public String uploadFile(MultipartFile file) throws IOException {
//StorePath storePath = storageClient.uploadFile((InputStream)file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
StorePath storePath = storageClient.uploadImageAndCrtThumbImage((InputStream)file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
System.out.println(imgHost + "/" + thumbImageConfig.getThumbImagePath(storePath.getFullPath()));
return getResAccessUrl(storePath);
}
/**
* 上传并返回半截存储路径
* @param file
* @return
* @throws IOException
*/
public String uploadFile_HalfPath(MultipartFile file) throws IOException {
StorePath storePath = storageClient.uploadFile((InputStream)file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
return storePath.getFullPath();
}
/**
* 根据半截路径获取可访问的全路径
* @param filePath
* @return
*/
public String getResAccessUrl(String filePath){
String fileUrl = imgHost + "/" + filePath;
return fileUrl;
}
/**
* 删除
* @param fileUrl
*/
public void deleteFile(String fileUrl){
StorePath storePath = StorePath.praseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(),storePath.getPath());
}
/**
* 下载
* @param fileUrl
* @return
* @throws IOException
*/
public byte[] downloadFile(String fileUrl) throws IOException {
StorePath storePath = StorePath.praseFromUrl(fileUrl);
String group = storePath.getGroup();
String path = storePath.getPath();
DownloadByteArray downloadByteArray = new DownloadByteArray();
byte[] bytes = storageClient.downloadFile(group, path, downloadByteArray);
return bytes;
}
/**
* 封装文件完整URL地址
* @param storePath
* @return
*/
private String getResAccessUrl(StorePath storePath) {
String fileUrl = imgHost + "/" + storePath.getFullPath();
return fileUrl;
}
public String getImgHost() {
return imgHost;
}
public void setImgHost(String imgHost) {
this.imgHost = imgHost;
}
}

上传、下载、删除示例:

TestController.java

package com.qfkj.upload.modules.controller;
import com.qfkj.upload.utils.FastDFSUploadUtils;
import com.qfkj.upload.utils.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

@Api("测试")
@RestController
public class TestController {
@Autowired
private FastDFSUploadUtils fastDFSClientUtils;
@ApiOperation(value = "测试上传",notes = "测试上传")
@PostMapping("/fdfs_upload")
public R fdfsUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return R.fail("请选择文件");
}
try {
String fileUrl= fastDFSClientUtils.uploadFile(file);
return R.ok((Object)fileUrl);
} catch (IOException e) {
e.printStackTrace();
}
return R.error();
}
@ApiOperation(value = "删除文件",notes = "删除文件")
@PostMapping("/fdfs_delete")
public R delete(@RequestParam("fileUrl") String fileUrl) {
try {
fastDFSClientUtils.deleteFile(fileUrl);
}catch (Exception e){
e.printStackTrace();
return R.error(e.toString());
}
return R.ok();
}
@ApiOperation(value = "下载文件",notes = "下载文件")
@GetMapping("/fdfs_download")
public void download(@RequestParam("fileUrl") String fileUrl, HttpServletResponse response) throws IOException {
byte[] bytes = fastDFSClientUtils.downloadFile(fileUrl);
// 这里只是为了整合fastdfs,所以写死了文件格式。需要在上传的时候保存文件名。下载的时候使用对应的格式
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("sb.webp", "UTF-8"));
response.setCharacterEncoding("UTF-8");
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

缩略图:

原始文件后加”_宽x高”,例如:_150x150

/d/pcjc/2022/33769247692433.webp

推荐阅读