二、实现fastdfs文件上传与延迟删除功能的Spring Boot项目
目录
- 1、Spring Boot 版本
- 2、 fastdfs 版本依赖
- 3、增加配置文件
- 4、创建FastDFS配置类,增加工具类
- 6、 增加对外接口
1、Spring Boot 版本
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.7</version>`在这里插入代码片`<relativePath/> <!-- lookup parent from repository --></parent>
2、 fastdfs 版本依赖
在您的pom.xml文件中,添加FastDFS客户端的依赖项。这里使用的是tobato提供的FastDFS客户端库。
<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><version>1.26.6</version></dependency>
3、增加配置文件
在application.properties或application.yml中配置FastDFS服务器的地址和其他相关参数。
# fastdfs文件系统
fdfs:tracker-list: #TrackerList参数,支持多个- 192.168.162.235:22122#- 192.168.162.239:22122so-timeout: 1501connect-timeout: 601thumb-image: #缩略图生成参数width: 200height: 200pool:max-total: 500max-wait-millis: 5000max-total-per-key: 100
4、创建FastDFS配置类,增加工具类
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import com.github.tobato.fastdfs.FdfsClientConfig;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;import lombok.extern.slf4j.Slf4j;/*** FastDFS文件上传下载包装类*/
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
@Component
@Slf4j
public class FileClient {@Autowiredprivate FastFileStorageClient storageClient;/*** 上传文件** @param file 文件对象* @return 文件访问地址* @throws IOException*/public String uploadFile(MultipartFile file) throws IOException {log.info("FileClient->uploadFile,file={}", file);String extension = getExtension(file);StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),extension, null);return getResAccessUrl(storePath);}public static String getExtension(MultipartFile file) {String trimStr = StringUtils.trim(file.getOriginalFilename());String extension = FilenameUtils.getExtension(trimStr);return extension;}public String uploadFile(InputStream inputStream, Long fileSize, String originalFilename) throws IOException {StorePath storePath = storageClient.uploadFile(inputStream, fileSize,FilenameUtils.getExtension(StringUtils.trim(originalFilename)), null);return getResAccessUrl(storePath);}public String uploadFile(File file) throws IOException {String extension = FilenameUtils.getExtension(StringUtils.trim(file.getName()));//Fastdf扩展名不能为空,默认为"txt"if (StringUtils.isEmpty(extension)) {extension = "txt";}StorePath storePath = storageClient.uploadFile(Files.newInputStream(file.toPath()), file.length(),extension, null);return getResAccessUrl(storePath);}/*** 将一段字符串生成一个文件上传** @param content 文件内容* @param fileExtension* @return*/public String uploadFile(String content, String fileExtension) {byte[] buff = content.getBytes(Charset.forName("UTF-8"));ByteArrayInputStream stream = new ByteArrayInputStream(buff);StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);return getResAccessUrl(storePath);}// 封装图片完整URL地址private String getResAccessUrl(StorePath storePath) {String fileUrl = "/"+storePath.getFullPath();return fileUrl;}/*** 传图片并同时生成一个缩略图 "JPG", "JPEG", "PNG", "GIF", "BMP", "WBMP"** @param file 文件对象* @return 文件访问地址* @throws IOException*/public String uploadImageAndCrtThumbImage(MultipartFile file) throws IOException {StorePath storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(),FilenameUtils.getExtension(file.getOriginalFilename()), null);return getResAccessUrl(storePath);}/*** 删除文件** @param fileUrl 文件访问地址*/public boolean deleteFile(String fileUrl) {if (StringUtils.isEmpty(fileUrl)) {log.error("删除文件异常,fileUrl is empty");return true;}try {StorePath storePath = StorePath.parseFromUrl(fileUrl);storageClient.deleteFile(storePath.getGroup(), storePath.getPath());} catch (Exception e) {log.error("删除文件异常:", e);return false;}return true;}}
6、 增加对外接口
@ApiOperation(value = "1、上传单个文件到FastDFS", notes = "")@PostMapping("uploadSingle")@ApiImplicitParams(value = {@ApiImplicitParam(name = "file", value = "单个文件", required = true, dataType = "__file",dataTypeClass =MultipartFile.class ) })public Result<FileItem> uploadSingle(FileUploadVo fileUploadVo) {log.info("FileApiController->uploadSingle processing......");FileItem fileItem = null;try {fileItem = uploadThenReturn(fileUploadVo.getFile(), fileUploadVo.getProjectCode(), fileUploadVo.getDeleteDelaySeconds());return ResultKit.succeed(fileItem);} catch (Exception e) {String errorInfo = LogKit.format("FileApiController->uploadSingleMap error,fileItem:{}.", fileItem);String content = errorInfo + ExceptionKit.getErrorInfoFromException(e);return ResultKit.error(ResultEnums.FAIL.getCode(),e.getMessage());}}private FileItem uploadThenReturn(MultipartFile file, String projectCode, Integer deleteDelaySeconds)throws IOException {String fileName = file.getOriginalFilename();log.info("FileApiController->uploadThenReturn start,fileName:{}.", fileName);String url = fileClient.uploadFile(file);String extension = FileClient.getExtension(file);FileItem fileItem = new FileItem(fileName, url, file.getSize(), extension);fileLogBizService.addLog(fileItem, projectCode, deleteDelaySeconds);log.info("FileApiController->uploadThenReturn end,fileItem:{}.", fileItem);return fileItem;}@ApiOperation(value = "2、删除文件")@PostMapping("delete")public Result<Boolean> delete(@RequestParam String projectCode, @RequestParam String token,@RequestParam String fileUrl, Integer delaySeconds) {log.info("FileApiController->delete start,fileUrl={}", fileUrl);boolean succeed = fileLogBizService.deleteFile(projectCode, fileUrl, delaySeconds);return ResultKit.succeedOrError(succeed);}@ApiOperation(value = "3、下载文件", notes = "")@GetMapping("download")public void download(@RequestParam String projectCode, @RequestParam String token, HttpServletResponse response,@RequestParam String url) throws IOException {String saveDir = FileOpenController.getTmpFileDir() + File.separator;// linux出现了,目录不会自动创建FileUtils.forceMkdir(new File(saveDir));try {String fdsfUrl = fileBizService.handleUrlDomain(url);FileKit.writeUrlFileToOutputStream(fdsfUrl, saveDir, response.getOutputStream());} catch (Exception e) {log.error("FileApiController->downloadFile error", e);}}public static String getTmpFileDir() {String saveDir = FileKit.getTmpDir() + File.separator + "file";return saveDir;}