MongoDB GridFS文件上传下载

MongoDB GridFS支持大文件存储:

GridFS用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等);

GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中;

GridFS 可以更好的存储大于16M的文件;

GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中;

每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。

spring-boot-starter-data-mongodb 基于GridFS实现文件的上传下载

application配置文件

server:
  port: 9001
spring:
  data:
    mongodb:
      uri: mongodb://root:123456@127.0.0.1:27017/fileInfo?readPreference=secondary&authSource=admin
  jackson:
    default-property-inclusion: non_null
  servlet:
    multipart:
      max-file-size: 10MB  #单个文件上传大小
      max-request-size: 100MB   #单次请求文件上传大小
  http:
    encoding:
      charset: UTF-8

 

自定义实体类记录上传文件的相关信息

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "tbl_data_record")
public class FileMetaDomain implements Serializable {

    private static final long serialVersionUID = 7733095063283270367L;

    @Id
    private String id;

    /* 文件信息存储在数据库中的uuid */ private List<Object> fileIds;

    /* 源文件名 */ private String fileName;

    /* 文件类型 */ private String contentType;

    /* 文件大小 */ private long size;

    /* 更新日期 */ private LocalDate updateTime = LocalDate.now();

    /* 创建日期 */ private LocalDate createTime = LocalDate.now();

    public FileMetaDomain(String id, String fileName, String contentType, long size){
        this.id = id; this.fileName = fileName;
        this.contentType = contentType;this.size = size;
    }
}

Dao层接口

@Repository
public interface GridFSRepository extends MongoRepository<FileMetaDomain,String> {

    @Query("{'fileName': ?0}")
    FileMetaDomain findByFileName(String fileName);
}

Service逻辑处理

public interface GridFsService {

    String saveFile(MultipartFile file) throws IOException;

    void downLoad(HttpServletResponse response, String fileName);
}

实现类

@Slf4j
@Service
public class GridFSServiceImpl implements GridFsService {

    private final MongoTemplate mongoTemplate;

    private final GridFSRepository repository;

    private final GridFsTemplate gridFsTemplate;

    @Autowired
    public GridFSServiceImpl(GridFSRepository repository, MongoTemplate mongoTemplate, GridFsTemplate gridFsTemplate) {
        this.repository = repository;
        this.mongoTemplate = mongoTemplate;
        this.gridFsTemplate = gridFsTemplate;
    }

    @Override
    public String saveFile(MultipartFile file) throws IOException {
        //源文件名
        String originalFilename = file.getOriginalFilename();
        //文件类型
        String contentType = file.getContentType();
        //文件大小
        long size = file.getSize();
        MongoDatabase db = mongoTemplate.getDb();
        GridFSBucket gridFSBucket = GridFSBuckets.create(db);
        ObjectId objectId = gridFSBucket.uploadFromStream(originalFilename, file.getInputStream());
        FileMetaDomain fileMetaDomain = new FileMetaDomain(objectId.toString(),originalFilename,contentType,size);
        FileMetaDomain fileMeta = repository.save(fileMetaDomain);
        return fileMeta.getId();
    }

    @Override
    public void downLoad(HttpServletResponse response, String fileName){
        FileMetaDomain fileMetaDomain = repository.findByFileName(fileName);
        Assert.notNull(fileMetaDomain,"当前下载的文件未上传到服务器");
        Query query = new Query();
        query.addCriteria(Criteria.where("filename").is(fileName));
        GridFSFile file = gridFsTemplate.findOne(query);
        MongoDatabase db = mongoTemplate.getDb();
        try {
            //文件名转码,支持中文文件名下载
            fileName = URLEncoder.encode(fileName,"UTF-8");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition","attachment;filename="+fileName);
            ServletOutputStream outputStream = response.getOutputStream();
            GridFSBuckets.create(db).downloadToStream(file.getObjectId(),outputStream);
            outputStream.flush();
            outputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

文件上传下载接口

@Slf4j
@RestController
@RequestMapping("/file")
public class GridFSController {

    private final GridFsService service;

    @Autowired
    public GridFSController(GridFsService service) {
        this.service = service;
    }

    @PostMapping("/upload")
    @ResponseBody
    public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file){
        try {
            if(ObjectUtils.isEmpty(file)){
                return ResponseEntity.ok().body("上传文件不能为空");
            }else {
                return ResponseEntity.ok().body(service.saveFile(file));
            }
        }catch (Exception e){
            log.error("[Upload Failed]",e);
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    @GetMapping("/download")
    public ResponseEntity<String> download(HttpServletResponse response, @RequestParam("fileName")String fileName){
        try {
            service.downLoad(response,fileName);
            return ResponseEntity.ok().body("SUCCESS");
        }catch (Exception e){
            log.error("[Download Failed]",e.getMessage());
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值