Spring CloudマイクロサービスにおけるMinIOを使用したファイルアップロード・ダウンロードAPIの実装方法

ファイルアップロード機能の実装

まずMinIOをデプロイし、設定情報を記述します。ここではNacosから動的にYML設定を読み込む方式を採用しています。

サービス層の実装:

@Autowired
private MinioStorageConfig storageConfig;

@Autowired
private MinioClient minioClient;

@Autowired
private FileMetadataRepository metadataRepository;

/**
 * シンプルファイルアップロード処理
 * @param multipartFile アップロード対象ファイル
 * @return アクセスURL
 */
public String handleFileUpload(MultipartFile multipartFile) throws Exception {
    String generatedName = FileNameGenerator.generateUniqueName(multipartFile);
    
    ObjectUploadRequest request = ObjectUploadRequest.builder()
            .bucket(storageConfig.getBucket())
            .object(generatedName)
            .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
            .contentType(multipartFile.getContentType())
            .build();
            
    minioClient.uploadObject(request);
    return storageConfig.getEndpoint() + "/" + storageConfig.getBucket() + "/" + generatedName;
}

/**
 * 業務ロジックを含むファイルアップロード
 * @param multipartFile アップロードファイル
 * @param metadata ファイルメタデータ情報
 * @return 登録件数
 */
public int saveFileWithMetadata(MultipartFile multipartFile, FileMetadata metadata) throws Exception {
    String uniqueId = UniqueIdGenerator.generate();
    String storagePath = PathBuilder.build(metadata.getServiceCode(), uniqueId, multipartFile);
    
    ObjectUploadRequest request = ObjectUploadRequest.builder()
            .bucket(storageConfig.getBucket())
            .object(storagePath)
            .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
            .contentType(multipartFile.getContentType())
            .build();
            
    minioClient.uploadObject(request);
    
    metadata.setUniqueId(uniqueId);
    metadata.setOriginalName(multipartFile.getOriginalFilename());
    metadata.setFileSizeBytes(multipartFile.getSize());
    metadata.setFileExtension(FileExtensionUtils.extract(multipartFile));
    metadata.setStorageLocation(storagePath);
    metadata.setCreator(AuthUtils.getCurrentUser());
    metadata.setCreatedAt(LocalDateTime.now());
    
    return metadataRepository.save(metadata);
}

ファイルダウンロード機能の実装

MinIOのgetObjectメソッドとdownloadObjectメソッドの違いを理解することが重要です。

getObjectメソッド:オブジェクトのデータストリームを直接取得 downloadObjectメソッド:オブジェクトをローカルファイルに保存

Webダウンロード処理にはgetObjectを使用します。

サービス層の実装:

@Autowired
private MinioStorageConfig storageConfig;

@Autowired
private MinioClient minioClient;

/**
 * ファイルダウンロード処理
 * @param storagePath 格納パス(例:service/module/2023/12/25/abc123def456.pdf)
 * @param responseStream HTTPレスポンス出力ストリーム
 */
public void processDownload(String storagePath, ServletOutputStream responseStream) {
    try (InputStream dataStream = minioClient.retrieveObject(
            RetrieveObjectRequest.builder()
                    .bucket(storageConfig.getBucket())
                    .object(storagePath)
                    .build())) {
        
        StreamUtils.copy(dataStream, responseStream);
        responseStream.flush();
        
    } catch (Exception ex) {
        log.error("ファイルダウンロード処理でエラー発生", ex);
        throw new FileDownloadException("ファイルのダウンロードに失敗しました");
    }
}

コントローラ層の実装:

/**
 * ファイルダウンロードエンドポイント
 * @param fileId ファイル一意ID
 * @param httpResponse HTTPレスポンスオブジェクト
 */
@GetMapping("/files/{fileId}/download")
public void downloadFile(@PathVariable String fileId, HttpServletResponse httpResponse) {
    FileMetadata metadata = metadataRepository.findByUniqueId(fileId)
            .orElseThrow(() -> new FileNotFoundException("ファイルが見つかりません: " + fileId));
    
    httpResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
    httpResponse.setHeader(HttpHeaders.CONTENT_DISPOSITION, 
            "attachment; filename=\"" + metadata.getOriginalName() + "\"");
    
    fileService.processDownload(metadata.getStorageLocation(), httpResponse.getOutputStream());
}

タグ: SpringCloud minio ファイルアップロード ファイルダウンロード マイクロサービス

8月17日 00:26 投稿