文章目录
springboot与fastdfs-client的整合
为Java操作fastdfs文件服务器提供的第三方工具:
GitHub源码: https://github.com/tobato/FastDFS_Client
注意:fastdfs-client 1.26.4版本以前的配置略有不同,具体参见上传文档。
1.pom.xml引入第三方工具类:
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.6</version>
</dependency>
2.在application.yml引入配置:
fdfs:
soTimeout: 1500 # socket连接超时时长
connectTimeout: 600 # 连接tracker服务器超时时长
reqHost: xxx.xxx.xxx.xxx # nginx访问地址
reqPort: 80 # nginx访问端口
thumbImage: # 缩略图的宽高
width: 150
height: 150
trackerList: # tracker服务配置地址列表,替换成自己服务的IP地址,支持多个
- xxx.xxx.xxx.xxx:22122
3.写个工具类 FastFileStorageClientUtil:
- 上传文件带MetaData
- 上传文件不带MetaData
- 上传图片并生成缩略图
- 下载文件
- 删除文件
package com.myt.fdfs.utils;
/*省略import*/
/**
* FastFileStorageClient客户端
* @author: mayating
* @create: 2020-12-25 11:36
*/
@Component
public class FastFileStorageClientUtil {
@Autowired
protected FastFileStorageClient storageClient;
@Autowired
private ThumbImageConfig thumbImageConfig;
@Value("${fdfs.reqHost}")
private String reqHost;
@Value("${fdfs.reqPort}")
private String reqPort;
/**
* 日志
*/
protected static Logger LOGGER = LoggerFactory.getLogger(FastFileStorageClientUtil.class);
/*******************************************上传文件/图片***********************************************************/
/**
* 上传文件 并且设置 MetaData
* @param file
* @param metaDataSet
* @return
*/
public String uploadFileAndMetaData(MultipartFile file,Set<MetaData> metaDataSet){
InputStream in = null;
try {
in = file.getInputStream();
//上传文件和MetaData
StorePath storePath = storageClient.uploadFile(in, file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), metaDataSet);
//获取 MetaData
//Set<MetaData> metadata = storageClient.getMetadata(storePath.getGroup(), storePath.getPath());
//删除文件
//storageClient.deleteFile(storePath.getGroup(),storePath.getPath());
//上传文件路径
return getResAccessUrl(storePath);
} catch (IOException e) {
LOGGER.error("文件上传失败:" + e.getMessage());
//throw new CustomException("文件上传失败:" + e.getMessage());
}
return null;
}
/**
* 上传文件 不带 MetaData
* @param file
* @return
*/
public String uploadFileWithOutMetaData(MultipartFile file){
InputStream in = null;
try {
in = file.getInputStream();
//上传文件和MetaData
StorePath storePath = storageClient.uploadFile(in, file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), null);
//删除文件
//storageClient.deleteFile(storePath.getGroup(),storePath.getPath());
String fileUrl = getResAccessUrl(storePath);
LOGGER.info("上传文件可访问路径:" + fileUrl);
//上传文件路径
return fileUrl;
} catch (IOException e) {
LOGGER.error("文件上传失败:" + e.getMessage());
//throw new CustomException("文件上传失败:" + e.getMessage());
}
return null;
}
/**
* 上传图片 并 生成缩略图
* 缩略图为上传文件名 + 缩略图后缀 _150×150,如xxx.jpg,缩略图为 xxx_150×150.jpg
*
* 实际样例如下:
* http://localhost:8098/M00/00/17/rBEAAl33pQaAWNQNAAHYvQQn-YE374.jpg
* http://localhost:8098/M00/00/17/rBEAAl33pQaAWNQNAAHYvQQn-YE374_150x150.jpg
* @param file
* @return
*/
public String uploadImageAndCrtThumbImage(MultipartFile file){
StorePath storePath = null;
InputStream in = null;
//StringBuilder stringBuilder = new StringBuilder();
try {
in = file.getInputStream();
storePath = storageClient.uploadImageAndCrtThumbImage(in, file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), null);
//获取从文件路径 即缩略图路径
String slavePath = thumbImageConfig.getThumbImagePath(storePath.getPath());
String masterUrl = getResAccessUrl(storePath);
LOGGER.info("图片路径:" + storePath);
LOGGER.info("图片可访问路径:" + masterUrl);
LOGGER.info("缩略图路径:" + slavePath);
return masterUrl;
} catch (IOException e) {
LOGGER.error("上传图片及生成缩略图失败:" + e.getMessage());
}finally {
//关流
if(null != in){
try {
in.close();
} catch (IOException e) {
LOGGER.error("输入流关闭失败:" + e.getMessage());
}
}
}
return null;
}
/*******************************************下载文件**********************************************************/
/**
* 下载文件
* @param groupName
* @param path
* @return
*/
public InputStream download(String groupName, String path ) {
InputStream ins = null;
try {
ins = storageClient.downloadFile(groupName, path, new DownloadCallback<InputStream>(){
@Override
public InputStream recv(InputStream ins) throws IOException {
// 将此ins返回给上面的ins
return ins;
}}) ;
}catch (FdfsServerException e){
//不起作用
LOGGER.error("文件不存在,下载失败:" + e.getErrorCode());
throw new CustomException("文件不存在,下载失败:" + e.getErrorCode());
}
return null ;
}
/*******************************************删除文件**********************************************************/
public void delFile(String filePath) {
storageClient.deleteFile(filePath);
}
/*******************************************公共方法**********************************************************/
/**
* 创建 元数据
* @return
*/
private Set<MetaData> createMetaData() {
Set<MetaData> metaDataSet = new HashSet<>();
metaDataSet.add(new MetaData("Author", "tobato"));
metaDataSet.add(new MetaData("CreateDate", "2016-01-05"));
return metaDataSet;
}
/**
* 封装文件完整URL地址
* @param storePath
* @return
*/
private String getResAccessUrl(StorePath storePath) {
String fileUrl = "http://" + reqHost + ":" + reqPort + "/" + storePath.getFullPath();
return fileUrl;
}
}
4.在controller层使用工具类:
- 上传图片并生成缩略图
- 上传文件
- 下载文件
- 删除文件
package com.myt.fdfs.controller;
/*省略import*/
/**
* @author: mayating
* @create: 2020-12-25 13:49
*/
@RestController
@RequestMapping("/files")
public class UploadController {
@Autowired
private FastFileStorageClientUtil dfsClient;
/**
* 上传图片并生成缩略图
* @param file
* @return
*/
@PostMapping("/fdfsUploadImage")
public Result fdfsUploadImage(@RequestParam("file")MultipartFile file){
String fileUrl = dfsClient.uploadImageAndCrtThumbImage(file);
return Result.SUCCESS(fileUrl);
}
/**
* 上传文件
* @param file
* @return
*/
@PostMapping("/fdfsUploadFile")
public Result fdfsUploadFile(@RequestParam("file")MultipartFile file){
String fileUrl = dfsClient.uploadFileWithOutMetaData(file);
return Result.SUCCESS(fileUrl);
}
/**
* 下载文件
* 请求示例地址:http://localhost/download?filePath=group1/M00/00/00/wKgIZVzZEF2ATP08ABC9j8AnNSs744.jpg
* @param filePath
* @param request
* @param response
* @throws IOException
*/
@GetMapping("/download")
public void download(String filePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
// group1/M00/00/00/wKgIZVzZEF2ATP08ABC9j8AnNSs744.jpg
String[] paths = filePath.split("/");
String groupName = null;
for (String item : paths) {
if (item.indexOf("group") != -1) {
groupName = item;
break;
}
}
String path = filePath.substring(filePath.indexOf(groupName) + groupName.length() + 1);
//输入流
InputStream input = dfsClient.download(groupName, path);
String fileName = paths[paths.length - 1];
//设置 response的响应头 能跳出下载窗口
//1.设置响应类型:
//获取文件的mime类型:content-type
String mimeType = request.getServletContext().getMimeType(fileName);
response.setHeader("content-type",mimeType);
//2.设置响应头打开方式:content-disposition
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//获取绑定了客户端的流
ServletOutputStream output = response.getOutputStream();
// 把输入流中的数据写入到输出流中
IOUtils.copy(input, output);
input.close();
}
/**
* 删除文件
* 请求地址示例:
* http://localhost/deleteFile?filePath=group1/M00/00/00/wKgIZVzZaRiAZemtAARpYjHP9j4930.jpg
* @param filePath
* @return
*/
@GetMapping("/deleteFile")
public Result delFile(String filePath){
dfsClient.delFile(filePath);
return Result.SUCCESS("文件删除成功");
}
}