ファイルアップロード機能の実装
まず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());
}