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

本文介绍了如何在Springboot2.6项目中,针对MongoDBGridFS处理大型GeoJSON数据,包括文件的流式上传、按FileID获取、以及删除功能,以解决系统迁移和外部OSS访问限制的问题。
摘要由CSDN通过智能技术生成

项目背景

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);
        }
    }

上传后检查存储桶:
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot使用MongoDB存取文件的步骤如下: 1.在全局配置文件(application.properties或application.yml)中配置MongoDB的连接信息,包括主机、端口和数据库名称。例如: ``` spring.data.mongodb.host=127.0.0.1 spring.data.mongodb.port=27017 spring.data.mongodb.database=users ``` 2.在项目的pom.xml文件中引入MongoDB的启动器依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> ``` 3.创建一个实体类来表示文件的数据结构,例如Blog类。可以根据需求设置相应的属性,比如作者、标题、内容、评论等: ``` package com.hang.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor public class Blog { private String id; private String author; private String title; private String content; private String communication; private int likeNumbers; private Date commitTime; } ``` 4.在需要使用MongoDB进行文件存取的地方,创建MongoClient对象,并通过它获取MongoDatabase对象。然后,可以通过MongoDatabase来获取MongoCollection对象,并使用其提供的方法进行文件的增删改查操作。例如,在测试类中的方法中,可以实现文件的插入操作: ``` import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import org.bson.Document; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class Springboot09MongodbApplicationTests { @Test void contextLoads() { MongoClient mongoClient = null; try { mongoClient = MongoClients.create("mongodb://127.0.0.1:27017"); MongoDatabase users = mongoClient.getDatabase("users"); MongoCollection<Document> test = users.getCollection("test"); test.insertOne(new Document("name","小红")); System.out.println("数据库连接成功,并成功插入数据"); }catch (Exception e){ e.printStackTrace(); }finally { mongoClient.close(); } } } ``` 通过以上步骤,就可以在Spring Boot使用MongoDB进行文件的存取了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Springboot集成MongoDB存储文件、读取文件](https://blog.csdn.net/harlan95/article/details/130154710)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Springboot整合Mongodb](https://blog.csdn.net/continue_gdufe/article/details/123936405)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值