Springboot + MongoDB 存储文件:上传文件及附属信息,文件保存到GridFS数据库,使用流式传输获取文件 可存储geojson、图片、视频等大型文件

项目背景

Springboot2.6 + MongoDB 存储大型 geojson数据
因为部分文件需要随系统保存,直接存储本地路径会导致系统迁移、Docker运行等出现问题,内网系统不能使用外部OSS,内部单独搭建OSS也难以维护,于是采用MongoDB的GridFS存储文件
获取时使用流式传输获取
示例包含导入、删除

后端代码

Controller

    @PostMapping("/import")
    @RequiresPermissions(PermissionConstant.ADD)
    public ResponseData<?> importGeoData(@RequestParam(value = "param1",required = false) String param1, @RequestParam(value = "param2",required = false) String param2,@RequestParam(value = "size",required = false)  long size, @RequestParam(value = "file",required = false) MultipartFile file) throws Exception {
        exampleUploadRequest uploadRequest = new exampleUploadRequest();
        uploadRequest.setParam1(param1);
        uploadRequest.setParam2(param2);
        uploadRequest.setSize(size);
        uploadRequest.setFile(file);
        return getResult(fileService.importExampleData(uploadRequest));
    }
    
    @Operation(summary = "根据FileId获取文件")
    @GetMapping("/getByFileId/{fileId}")
    @RequiresPermissions(PermissionConstant.GET)
    public ResponseEntity<StreamingResponseBody> getByFileId(@PathVariable("fileId") String fileId) {
        return ResponseEntity.ok()
                .header("Content-Type", "application/json")
                .header("responseType", "custom type")
                .body(fileService.getFile(fileId));
    }

Entity

//Dto:
@Data
public class ExampleUploadRequest {
    private String param1;
    private String param2;
    MultipartFile file;
    private Long size;
}

//实体:
@Data
@Document
@FieldDefaults(level = AccessLevel.PRIVATE)
@Schema(description = "附属文件数据")
public class TbExample extends BaseEntity implements Serializable {

    @Schema(description = "fileID")
    @Indexed(unique = true)
    private String fileID;

    @Schema(description = "参数1")
    private String param1;

    @Schema(description = "参数2")
    private String param2;

    @Schema(description = "文件大小")
    private Long size;
}

ServiceImpl

//------------导入-------------:
    @Override
    public Boolean importExampleData(exampleUploadRequest uploadRequest) throws IOException {
    //存储附属数据
        TbExample exampleData = new Tbexample();
        exampleData.setId(RandomIdUtil.generateSimpleUuid());
        //复制属性
        BeanUtils.copyProperties(uploadRequest, exampleData);
        exampleData.setCreateTime(LocalDateTime.now());

        // 使用 GridFS 保存文件,可以改为获取File的文件名保存(uploadRequest.getFile().getName()))
        String fileID = saveFileToGridFS(uploadRequest.getFile(), exampleData.getId() + ".json");
        exampleData.setFileID(fileID); // 保存 GridFS 生成的 fileID

        exampleRepository.save(exampleData);
        return true;
    }
    private String saveFileToGridFS(MultipartFile file, String fileName) throws IOException {
        // 将 MultipartFile 转换为 InputStream
        try (InputStream inputStream = file.getInputStream()) {
            // 保存文件到 GridFS
            Object fileObjectId = gridFsTemplate.store(inputStream, fileName);
            return fileObjectId.toString();
        }
    }
// ------------- 获取 ------------
   @Override
    public StreamingResponseBody getFile(String fileID) {
        GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(fileID)));
        if (gridFSFile == null) {
            throw new ViewException(ViewExceptionType.DATA_NOT_EXISTS);
        }

        return outputStream -> {
            try (InputStream inputStream = gridFsTemplate.getResource(gridFSFile).getInputStream()) {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            } catch (IOException e) {
                // 处理异常,例如记录日志或者抛出运行时异常
                log.error("Error occurred while transferring file content", e);
                throw new RuntimeException("Error occurred while transferring file content", e);
            }
        };
    }
// ------------ 删除 ---------------------
    @Override
    public Boolean deleteById(String id) {
        TbExample tbexample = exampleRepository.findById(id).orElse(null);
        if (tbexample != null) {
            // 首先,删除数据库记录
            exampleRepository.deleteById(id);

            // 然后,尝试从GridFS中删除文件
            try {
                // 如果使用的是文件ID作为GridFS中的_id
                // gridFsTemplate.delete(new Query(Criteria.where("_id").is(tbexample.getFileID())));

                // 如果文件是通过文件名存储在GridFS中,您需要使用文件名来删除
                gridFsTemplate.delete(new Query(Criteria.where("filename").is(tbexample.getId() + ".json")));

                return true;
            } catch (Exception e) {
                log.error("Failed to delete file from GridFS: " + tbexample.getFileID(), e);
                throw new ViewException(ViewExceptionType.SERVER_ERROR, "删除文件失败");
            }
        } else {
            throw new ViewException(ViewExceptionType.DATA_NOT_EXISTS);
        }
    }

上传后检查存储桶:
Springboot + MongoDB 存储文件:上传文件及附属信息,文件保存到GridFS数据库,使用流式传输获取文件 可存储geojson、图片、视频等大型文件_第1张图片

你可能感兴趣的:(java,数据库,spring,boot,mongodb)