最近在做一个课程,需要用讲一下SpringBoot 使用文件上传的功能,选择了FastDFS作为文件存储OSS。Spring Boot是最新的3.3.0版本,JDK版本是17,中间有一些坑,下面记录一下。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version><relativePath/> <!-- lookup parent from repository --> </parent><properties><java.version>17</java.version> </properties>
一,安装FastDFS
FastDFS高可用集群架构配置搭建及使用_fdfs 集群 使用-CSDN博客
二,集成
1,引入pom
<!-- FastDFS Start 如果已经引入了log4j的实现,需要排除掉fastdfs的--> <dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><version>1.27.2</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion><exclusion><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId></exclusion><exclusion><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></exclusion><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions> </dependency> <!-- 注解@PostConstruct包路径在jdk17是无效的, 需要补充下面的依赖 --> <dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version> </dependency> <!-- FastDFS End -->
2,导入FastDFS配置
fdfs:open: trueso-timeout: 1501connect-timeout: 601thumb-image: #缩略图生成参数width: 150height: 150tracker-list: #TrackerList参数,支持多个- 10.250.112.141:22122file:domain: http://10.250.112.143:8888/
3,工具类
(1)FastDFSClient
import com.github.tobato.fastdfs.domain.fdfs.MetaData; import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray; import com.github.tobato.fastdfs.service.FastFileStorageClient; import jakarta.annotation.Resource; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URLEncoder; import java.util.HashSet; import java.util.Set;@Component public class FastDFSClient {@Resourceprivate FastFileStorageClient fastFileStorageClient;/*** 上传** @param file* @return* @throws IOException*/public StorePath upload(MultipartFile file) throws IOException {// 设置文件信息Set<MetaData> mataData = new HashSet<>();mataData.add(new MetaData("author", "fastdfs"));mataData.add(new MetaData("description", file.getOriginalFilename()));// 上传StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(),FilenameUtils.getExtension(file.getOriginalFilename()),null);return storePath;}/*** 上传文件** @param file* @return* @throws FileNotFoundException*/public String uploadFile(String file) throws FileNotFoundException {File file1 = new File(file);if (!file1.exists()) {return null;}FileInputStream fileInputStream = new FileInputStream(file1);// 上传文件和MetadataStorePath path = fastFileStorageClient.uploadFile(fileInputStream, file1.length(), FilenameUtils.getExtension(file1.getName()),null);return path.getFullPath();}/*** 上传文件** @param file* @return* @throws IOException*/public String uploadFile(File file) throws IOException {if (file == null) {return null;}FileInputStream fileInputStream = new FileInputStream(file);// 上传文件和MetadataStorePath path = fastFileStorageClient.uploadFile(fileInputStream, file.length(), FilenameUtils.getExtension(file.getName()),null);fileInputStream.close();return path.getFullPath();}/*** 删除** @param path*/public void delete(String path) {fastFileStorageClient.deleteFile(path);}/*** 删除** @param group* @param path*/public void delete(String group, String path) {fastFileStorageClient.deleteFile(group, path);}/*** 文件下载** @param path 文件路径,例如:/group1/path=M00/00/00/itstyle.png* @param filename 下载的文件命名* @return*/public void download(String path, String filename, HttpServletResponse response) throws IOException {// 获取文件StorePath storePath = StorePath.parseFromUrl(path);if (StringUtils.isBlank(filename)) {filename = FilenameUtils.getName(storePath.getPath());}byte[] bytes = fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());response.reset();response.setContentType("applicatoin/octet-stream");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));ServletOutputStream out = response.getOutputStream();out.write(bytes);out.close();} }
(2)FastDFSConfig
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) // 解决jmx重复注册bean的问题 @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) public class FastDFSConfig { }
(3)FastDfsStorePath
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import lombok.Data;@Data public class FastDfsStorePath {private String group;private String path;private String fullPath;private String fileUrl;public FastDfsStorePath(StorePath storePath) {this.group = storePath.getGroup();this.path = storePath.getPath();this.fullPath = storePath.getFullPath();} }
4,上传文件接口
@Value("${file.domain}") private String fileDomain;@Operation(summary = "上传文件") @PostMapping("/file") @ResponseBody public RestResponse<FastDfsStorePath> updateFile(@RequestParam("file") MultipartFile file) throws IOException {log.info("=====>文件名: {}", file.getOriginalFilename());StorePath storePath = fastDFSClient.upload(file);FastDfsStorePath fastDfsStorePath = new FastDfsStorePath(storePath);fastDfsStorePath.setFileUrl(fileDomain + storePath.getFullPath());return RestResponse.success(fastDfsStorePath); }
接口返回
{
"code": 200,
"message": null,
"data": {
"group": "group1",
"path": "M00/00/01/CpaE3mZer6WANEKKADTPweiDcA8273.png",
"fullPath": "group1/M00/00/01/CpaE3mZer6WANEKKADTPweiDcA8273.png",
"fileUrl": "http://10.250.112.143:8888/group1/M00/00/01/CpaE3mZer6WANEKKADTPweiDcA8273.png"
},
"requestId": null,
"success": true
}
完毕!