SpringBoot|SpringBoot 集成MongoDB实现文件上传功能

目录

  • 前言
  • 环境
  • 代码实现
  • 测试
  • 源码

前言
  • 记录下SpringBoot集成MongoDB实现文件上传的步骤
  • MongoDB - 5.0.6安装包
链接: https://pan.baidu.com/s/1_7nJDe3ndraNyo3vGWOXhg?pwd=i4cv
提取码: i4cv

环境
SpringBoot - 2.5.12
MongoDB - 5.0.6

代码实现 pom.xml
org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-data-mongodborg.projectlomboklombokcn.hutoolhutool-all4.5.1

application.yml
server:port: 31091spring:servlet:multipart:max-file-size: 100MBdata:mongodb:host: 127.0.0.1port: 27017database: adminusername: rootpassword: sundayfileUploadService:impl: fileMongoServiceImpl

【SpringBoot|SpringBoot 集成MongoDB实现文件上传功能】MongoConfig.java
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoDatabase; import com.mongodb.client.gridfs.GridFSBucket; import com.mongodb.client.gridfs.GridFSBuckets; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Description MongoDB配置类 */@Configurationpublic class MongoConfig {/*** 数据库配置信息*/@Value("${spring.data.mongodb.database}")private String db; /*** GridFSBucket用于打开下载流* @param mongoClient* @return*/@Beanpublic GridFSBucket getGridFSBucket(MongoClient mongoClient){MongoDatabase mongoDatabase = mongoClient.getDatabase(db); return GridFSBuckets.create(mongoDatabase); }}

FileUploadController.java
import com.coisini.mongodb.model.ResponseMessage; import com.coisini.mongodb.service.FileUploadService; import com.coisini.mongodb.vo.FileExportVo; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.List; import java.util.Objects; /** * @Description 文件上传接口 */@Slf4j@RestController@RequestMapping("/file")public class FileUploadController {/*** 文件上传实现类*/@Resource(name="${fileUploadService.impl}")private FileUploadService fileUploadService; * 文件上传* @param file* @return@PostMapping("/upload")public ResponseMessage uploadFile(@RequestParam(value = "https://www.it610.com/article/file") MultipartFile file) {try {return ResponseMessage.ok("上传成功", fileUploadService.uploadFile(file)); } catch (Exception e) {log.error("文件上传失败:", e); return ResponseMessage.error(e.getMessage()); }}* 多文件上传* @param files@PostMapping("/uploadFiles")public ResponseMessage uploadFile(@RequestParam(value = "https://www.it610.com/article/files") List files) {return ResponseMessage.ok("上传成功", fileUploadService.uploadFiles(files)); * 文件下载* @param fileId@GetMapping("/download/{fileId}")public ResponseEntity fileDownload(@PathVariable(name = "fileId") String fileId) {FileExportVo fileExportVo = fileUploadService.downloadFile(fileId); if (Objects.nonNull(fileExportVo)) {return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\"" + fileExportVo.getFileName() + "\"").header(HttpHeaders.CONTENT_TYPE, fileExportVo.getContentType()).header(HttpHeaders.CONTENT_LENGTH, fileExportVo.getFileSize() + "").header("Connection", "close").body(fileExportVo.getData()); } else {return ResponseEntity.status(HttpStatus.NOT_FOUND).body("file does not exist"); * 文件删除@DeleteMapping("/remove/{fileId}")public ResponseMessage removeFile(@PathVariable(name = "fileId") String fileId) {fileUploadService.removeFile(fileId); return ResponseMessage.ok("删除成功"); }
FileUploadService.java
import com.coisini.mongodb.vo.FileExportVo; import org.springframework.web.multipart.MultipartFile; import java.util.List; /** * @Description 文件上传接口 */public interface FileUploadService {/*** 文件上传* @param file* @return*/FileExportVo uploadFile(MultipartFile file) throws Exception; /*** 多文件上传* @param files* @return*/List uploadFiles(List files); /*** 文件下载* @param fileId* @return*/FileExportVo downloadFile(String fileId); /*** 文件删除* @param fileId*/void removeFile(String fileId); }

FileMongoServiceImpl.java
import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import com.coisini.mongodb.model.MongoFile; import com.coisini.mongodb.repository.MongoFileRepository; import com.coisini.mongodb.service.FileUploadService; import com.coisini.mongodb.util.MD5Util; import com.coisini.mongodb.vo.FileExportVo; import com.mongodb.client.gridfs.GridFSBucket; import com.mongodb.client.gridfs.GridFSDownloadStream; import com.mongodb.client.gridfs.model.GridFSFile; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.types.Binary; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.gridfs.GridFsResource; import org.springframework.data.mongodb.gridfs.GridFsTemplate; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; /** * @Description MongoDB文件上传实现类 */@Slf4j@Service("fileMongoServiceImpl")@RequiredArgsConstructor(onConstructor = @__(@Autowired))public class FileMongoServiceImpl implements FileUploadService {private final MongoFileRepository mongoFileRepository; private final MongoTemplate mongoTemplate; private final GridFsTemplate gridFsTemplate; private final GridFSBucket gridFSBucket; /*** 多文件上传* @param files* @return*/@Overridepublic List uploadFiles(List files) {return files.stream().map(file -> {try {return this.uploadFile(file); } catch (Exception e) {log.error("文件上传失败", e); return null; }}).filter(Objects::nonNull).collect(Collectors.toList()); }/*** 文件上传* @param file* @return* @throws Exception*/@Overridepublic FileExportVo uploadFile(MultipartFile file) throws Exception {if (file.getSize() > 16777216) {return this.saveGridFsFile(file); } else {return this.saveBinaryFile(file); }}/*** 文件下载* @param fileId* @return*/@Overridepublic FileExportVo downloadFile(String fileId) {Optional option = this.getBinaryFileById(fileId); if (option.isPresent()) {MongoFile mongoFile = option.get(); if(Objects.isNull(mongoFile.getContent())){option = this.getGridFsFileById(fileId); }}return option.map(FileExportVo::new).orElse(null); }/*** 文件删除* @param fileId*/@Overridepublic void removeFile(String fileId) {Optional option = this.getBinaryFileById(fileId); if (option.isPresent()) {if (Objects.nonNull(option.get().getGridFsId())) {this.removeGridFsFile(fileId); } else {this.removeBinaryFile(fileId); }}}/*** 删除Binary文件* @param fileId*/public void removeBinaryFile(String fileId) {mongoFileRepository.deleteById(fileId); }/*** 删除GridFs文件* @param fileId*/public void removeGridFsFile(String fileId) {// TODO 根据id查询文件MongoFile mongoFile = mongoTemplate.findById(fileId, MongoFile.class ); if(Objects.nonNull(mongoFile)){// TODO 根据文件ID删除fs.files和fs.chunks中的记录Query deleteFileQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId())); gridFsTemplate.delete(deleteFileQuery); // TODO 删除集合mongoFile中的数据Query deleteQuery = new Query(Criteria.where("id").is(fileId)); mongoTemplate.remove(deleteQuery, MongoFile.class); }}/*** 保存Binary文件(小文件)* @param file* @return* @throws Exception*/public FileExportVo saveBinaryFile(MultipartFile file) throws Exception {String suffix = getFileSuffix(file); MongoFile mongoFile = mongoFileRepository.save(MongoFile.builder().fileName(file.getOriginalFilename()).fileSize(file.getSize()).content(new Binary(file.getBytes())).contentType(file.getContentType()).uploadDate(new Date()).suffix(suffix).md5(MD5Util.getMD5(file.getInputStream())).build()); return new FileExportVo(mongoFile); }/*** 保存GridFs文件(大文件)* @param file* @return* @throws Exception*/public FileExportVo saveGridFsFile(MultipartFile file) throws Exception {String suffix = getFileSuffix(file); String gridFsId = this.storeFileToGridFS(file.getInputStream(), file.getContentType()); MongoFile mongoFile = mongoTemplate.save(MongoFile.builder().fileName(file.getOriginalFilename()).fileSize(file.getSize()).contentType(file.getContentType()).uploadDate(new Date()).suffix(suffix).md5(MD5Util.getMD5(file.getInputStream())).gridFsId(gridFsId).build()); return new FileExportVo(mongoFile); }/*** 上传文件到Mongodb的GridFs中* @param in* @param contentType* @return*/public String storeFileToGridFS(InputStream in, String contentType){String gridFsId = IdUtil.simpleUUID(); // TODO 将文件存储进GridFS中gridFsTemplate.store(in, gridFsId , contentType); return gridFsId; }/*** 获取Binary文件* @param id* @return*/public Optional getBinaryFileById(String id) {return mongoFileRepository.findById(id); }/*** 获取Grid文件* @param id* @return*/public Optional getGridFsFileById(String id){MongoFile mongoFile = mongoTemplate.findById(id , MongoFile.class ); if(Objects.nonNull(mongoFile)){Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(mongoFile.getGridFsId())); try {// TODO 根据id查询文件GridFSFile fsFile = gridFsTemplate.findOne(gridQuery); // TODO 打开流下载对象GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId()); if(in.getGridFSFile().getLength() > 0){// TODO 获取流对象GridFsResource resource = new GridFsResource(fsFile, in); // TODO 获取数据mongoFile.setContent(new Binary(IoUtil.readBytes(resource.getInputStream()))); return Optional.of(mongoFile); }else {return Optional.empty(); }}catch (IOException e){log.error("获取MongoDB大文件失败", e); }}return Optional.empty(); }/*** 获取文件后缀* @param file* @return*/private String getFileSuffix(MultipartFile file) {String suffix = ""; if (Objects.requireNonNull(file.getOriginalFilename()).contains(".")) {suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); }return suffix; }}

MongoFileRepository.java
import com.coisini.mongodb.model.MongoFile; import org.springframework.data.mongodb.repository.MongoRepository; /** * @Description MongoDB文件仓储 */public interface MongoFileRepository extends MongoRepository {}

MongoFile.java
import lombok.Builder; import lombok.Data; import org.bson.types.Binary; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.Date; /** * @Description MongoDB文件实体 */@Document@Builder@Datapublic class MongoFile {/*** 主键*/@Idpublic String id; /*** 文件名称*/public String fileName; /*** 文件大小*/public long fileSize; /*** 上传时间*/public Date uploadDate; /*** MD5值*/public String md5; /*** 文件内容*/private Binary content; /*** 文件类型*/public String contentType; /*** 文件后缀名*/public String suffix; /*** 文件描述*/public String description; /*** 大文件管理GridFS的ID*/private String gridFsId; }

ResponseMessage.java
/** * @Description 统一消息 */public class ResponseMessage {private String status; private String message; private T data; // 省略}

FileExportVo.java
import java.util.Objects; /** * @Description 统一文件下载vo */@Datapublic class FileExportVo {private String fileId; private String fileName; private String contentType; private String suffix; private long fileSize; @JsonIgnoreprivate byte[] data; public FileExportVo(MongoFile mongoFile) {BeanUtil.copyProperties(mongoFile, this); if (Objects.nonNull(mongoFile.getContent())) {this.data = https://www.it610.com/article/mongoFile.getContent().getData(); }this.fileId = mongoFile.getId(); }}

MD5Util.java
import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * @Description MD5工具类 */public class MD5Util {/*** 获取该输入流的MD5值*/public static String getMD5(InputStream is) throws NoSuchAlgorithmException, IOException {StringBuffer md5 = new StringBuffer(); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = is.read(dataBytes)) != -1) {md.update(dataBytes, 0, nread); }; byte[] mdbytes = md.digest(); // convert the byte to hex formatfor (int i = 0; i < mdbytes.length; i++) {md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); }return md5.toString(); }}


测试 文件上传
SpringBoot|SpringBoot 集成MongoDB实现文件上传功能
文章图片

多文件上传
SpringBoot|SpringBoot 集成MongoDB实现文件上传功能
文章图片

文件下载
SpringBoot|SpringBoot 集成MongoDB实现文件上传功能
文章图片

文件删除
SpringBoot|SpringBoot 集成MongoDB实现文件上传功能
文章图片


源码 GitHub:https://github.com/Maggieq8324/java-learn-demo/tree/master/springboot-mongodb-file
Gitee:https://gitee.com/maggieq8324/java-learn-demo/tree/master/springboot-mongodb-file
到此这篇关于SpringBoot 集成MongoDB实现文件上传的文章就介绍到这了,更多相关SpringBoot 集成MongoDB文件上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读