<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SpringBoot之MongoDB附件操作

      前言

      近期自己針對附件上傳進一步學習,為了彌足項目中文件上傳的漏洞,保證文件上傳功能的健壯性和可用性,現在我將自己在這一塊的心得總結如下:

      一、pom.xml依賴的引入

      <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
      
              <!-- mongodb -->
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-data-mongodb</artifactId>
              </dependency>
      
              <!-- lombok -->
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
              </dependency>
      
              <!-- hutool -->
              <dependency>
                  <groupId>cn.hutool</groupId>
                  <artifactId>hutool-all</artifactId>
                  <version>4.5.1</version>
      </dependency>
      

      二.application.yml配置信息

      server:
        port: 31091
      
      spring:
        servlet:
          multipart:
            max-file-size: 100MB
        data:
          mongodb:
            host: localhost
            port: 27017
            database: feng
      
      fileUploadService:
        impl: fileMongoServiceImpl
      

       三、MongoDB配置類

      /**
       * @Description MongoDB配置類
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      @Configuration
      public class MongoConfig {
          /**
           * 數據庫配置信息
           */
          @Value("${spring.data.mongodb.database}")
          private String db;
      
          /**
           * GridFSBucket用于打開下載流
           * @param mongoClient
           * @return
           */
          @Bean
          public GridFSBucket getGridFSBucket(MongoClient mongoClient){
              MongoDatabase mongoDatabase = mongoClient.getDatabase(db);
              return GridFSBuckets.create(mongoDatabase);
          }
      }
      

       四、MongoDB文件實體

      /**
       * @Description MongoDB文件實體
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      @Document
      @Builder
      @Data
      public class MongoFile {
      
          /**
           * 主鍵
           */
          @Id
          public 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;
      
      }
      

       五、返回統一消息處理類

      /**
       * @Description 統一消息
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      public class ResponseMessage<T> {
      
          private String status;
          private String message;
          private T data;
      
          public static ResponseMessage<?> ok() {
              return create("0", (String)null, (Object)null);
          }
      
          public static ResponseMessage<?> ok(String message) {
              return create("0", message, (Object)null);
          }
      
          public static <T> ResponseMessage<T> ok(String message, T data) {
              return create("0", message, data);
          }
      
          public static <T> ResponseMessage<T> ok(T data) {
              return create("0", (String)null, data);
          }
      
          public static ResponseMessage<?> error() {
              return create("1", (String)null, (Object)null);
          }
      
          public static ResponseMessage<?> error(String message) {
              return create("1", message, (Object)null);
          }
      
          public static <T> ResponseMessage<T> error(String message, T data) {
              return create("1", message, data);
          }
      
          private static <T> ResponseMessage<T> create(String status, String message, T data) {
              ResponseMessage<T> t = new ResponseMessage();
              t.setStatus(status);
              t.setMessage(message);
              t.setData(data);
              return t;
          }
      
          public ResponseMessage() {
          }
      
          public String getStatus() {
              return this.status;
          }
      
          public String getMessage() {
              return this.message;
          }
      
          public T getData() {
              return this.data;
          }
      
          public void setStatus(final String status) {
              this.status = status;
          }
      
          public void setMessage(final String message) {
              this.message = message;
          }
      
          public void setData(final T data) {
              this.data = data;
          }
      
      }
      

      六、統一文件下載vo

      /**
       * @Description 統一文件下載vo
       * @author songwp
       * @date Apr 8, 2022
       * @version 1.0
       */
      @Data
      public class FileExportVo {
      
          private String fileId;
      
          private String fileName;
      
          private String contentType;
      
          private String suffix;
      
          private long fileSize;
      
          @JsonIgnore
          private byte[] data;
      
          public FileExportVo(MongoFile mongoFile) {
              BeanUtil.copyProperties(mongoFile, this);
              if (Objects.nonNull(mongoFile.getContent())) {
                  this.data = mongoFile.getContent().getData();
              }
              this.fileId = mongoFile.getId();
          }
      
      }
      

       七、MD5工具類

      /**
       * @Description MD5工具類
       * @date Apr 8, 2022
       * @version 1.0
       */
      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 format
              for (int i = 0; i < mdbytes.length; i++) {
                  md5.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
              }
              return md5.toString();
          }
      }
      

      八、MongoDB文件倉儲

      /**
       * @Description MongoDB文件倉儲
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      public interface MongoFileRepository extends MongoRepository<MongoFile, String> {}
      

      九、文件上傳業務接口

      /**
       * @Description 文件上傳接口
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      public interface FileUploadService {
      
          /**
           * 文件上傳
           * @param file
           * @return
           */
          FileExportVo uploadFile(MultipartFile file) throws Exception;
      
          /**
           * 多文件上傳
           * @param files
           * @return
           */
          List<FileExportVo> uploadFiles(List<MultipartFile> files);
      
          /**
           * 文件下載
           * @param fileId
           * @return
           */
          FileExportVo downloadFile(String fileId);
      
          /**
           * 文件刪除
           * @param fileId
           */
          void removeFile(String fileId);
      
      }
      

      十、MongoDB文件上傳實現類

      /**
       * @Description MongoDB文件上傳實現類
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      @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
           */
          @Override
          public List<FileExportVo> uploadFiles(List<MultipartFile> 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
           */
          @Override
          public FileExportVo uploadFile(MultipartFile file) throws Exception {
              if (file.getSize() > 16777216) {
                  return this.saveGridFsFile(file);
              } else {
                  return this.saveBinaryFile(file);
              }
          }
      
          /**
           * 文件下載
           * @param fileId
           * @return
           */
          @Override
          public FileExportVo downloadFile(String fileId) {
              Optional<MongoFile> 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
           */
          @Override
          public void removeFile(String fileId) {
              Optional<MongoFile> 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<MongoFile> getBinaryFileById(String id) {
              return mongoFileRepository.findById(id);
          }
      
          /**
           * 獲取Grid文件
           * @param id
           * @return
           */
          public Optional<MongoFile> 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;
          }
      

      十一、文件上傳接口-控制器

      /**
       * @Description 文件上傳接口
       * @author songwp
       * @date Apr 17, 2022
       * @version 1.0
       */
      @Slf4j
      @RestController
      @RequestMapping("/file")
      public class FileUploadController {
      
          /**
           * 文件上傳實現類
           */
          @Resource
          private FileUploadService fileUploadService;
      
          /**
           * 文件上傳
           * @param file
           * @return
           */
          @PostMapping("/upload")
          public ResponseMessage<?> uploadFile(@RequestParam(value = "file") MultipartFile file) {
              try {
                  return ResponseMessage.ok("上傳成功", fileUploadService.uploadFile(file));
              } catch (Exception e) {
                  log.error("文件上傳失敗:", e);
                  return ResponseMessage.error(e.getMessage());
              }
          }
      
          /**
           * 多文件上傳
           * @param files
           * @return
           */
          @PostMapping("/uploadFiles")
          public ResponseMessage<?> uploadFile(@RequestParam(value = "files") List<MultipartFile> files) {
              try {
                  return ResponseMessage.ok("上傳成功", fileUploadService.uploadFiles(files));
              } catch (Exception e) {
                  return ResponseMessage.error(e.getMessage());
              }
          }
      
          /**
           * 文件下載
           * @param fileId
           * @return
           */
          @GetMapping("/download/{fileId}")
          public ResponseEntity<Object> 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");
              }
          }
      
          /**
           * 文件刪除
           * @param fileId
           * @return
           */
          @DeleteMapping("/remove/{fileId}")
          public ResponseMessage<?> removeFile(@PathVariable(name = "fileId") String fileId) {
              fileUploadService.removeFile(fileId);
              return ResponseMessage.ok("刪除成功");
          }
      
      }
      

      十二、接口測試

       1.單個文件上傳

          2.多文件上傳

        3.文件下載

        4.文件刪除

      posted @ 2022-07-11 11:30  [奮斗]  閱讀(343)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久久久国产精品人妻| 亚洲精品日韩精品久久| 亚洲国产午夜精品福利| 亚洲色一色噜一噜噜噜| 免费无码成人AV片在线| 日韩精品毛片一区到三区| 成在人线av无码免费高潮水老板| 国产精品久久久久无码网站| 色综合久久中文综合网| 粉嫩av国产一区二区三区| 亚洲色大成网站WWW永久麻豆 | 区一区二区三区中文字幕| 国产欧美亚洲精品a| 亚洲丰满老熟女激情av| 厦门市| 亚洲精品日韩精品久久| 国产美女午夜福利视频| 亚洲人成人无码网WWW电影首页| 亚洲五月丁香综合视频| 国产成人精品永久免费视频| 激情综合网激情五月伊人| 国产精品三级中文字幕| 67194熟妇在线观看线路| 中文字幕 日韩 人妻 无码| 国产精品大全中文字幕| 少妇激情一区二区三区视频| 好硬好湿好爽好深视频| 精品日韩精品国产另类专区| 国产不卡一区二区四区| 欧美另类图区清纯亚洲| 亚洲综合伊人五月天中文 | 日本一级午夜福利免费区 | 精品国产成人一区二区| 兴业县| 精品视频不卡免费观看| 亚洲精品自拍在线视频| 四虎www永久在线精品| 欧美一区二区三区欧美日韩亚洲 | 亚洲精品无码AV人在线观看国产| 国产口爆吞精在线视频2020版| 久久婷婷五月综合色一区二区|