Files
goldenChart/backend/src/main/java/com/goldenchart/controller/VerificationIssueImageController.java
T
2026-05-27 15:41:19 +09:00

88 lines
3.7 KiB
Java

package com.goldenchart.controller;
import com.goldenchart.dto.VerificationIssueImageDto;
import com.goldenchart.service.VerificationIssueImageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/verification-issues/{issueId}/images")
@RequiredArgsConstructor
@Slf4j
public class VerificationIssueImageController {
private final VerificationIssueImageService service;
@GetMapping
public ResponseEntity<List<VerificationIssueImageDto>> list(@PathVariable Long issueId) {
return ResponseEntity.ok(service.listByIssue(issueId));
}
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> upload(
@PathVariable Long issueId,
@RequestParam("files") List<MultipartFile> files) {
try {
return ResponseEntity.ok(service.upload(issueId, files));
} catch (IllegalArgumentException e) {
log.warn("[VerificationImage] upload rejected issueId={}: {}", issueId, e.getMessage());
return ResponseEntity.badRequest().body(Map.of("message", toUserMessage(e.getMessage())));
} catch (IOException e) {
log.error("[VerificationImage] upload io error issueId={}", issueId, e);
return ResponseEntity.internalServerError()
.body(Map.of("message", "이미지 저장에 실패했습니다. 잠시 후 다시 시도하세요."));
}
}
private static String toUserMessage(String code) {
if (code == null) return "업로드할 수 없습니다.";
return switch (code) {
case "unsupported image type" -> "지원하지 않는 이미지 형식입니다. (jpeg, png, gif, webp, bmp)";
case "file too large" -> "이미지 크기는 파일당 5MB 이하여야 합니다.";
case "no files", "no valid image files" -> "업로드할 이미지가 없습니다.";
default -> code.startsWith("max images exceeded")
? "이슈당 첨부 이미지는 최대 30장까지입니다."
: code.startsWith("issue not found") ? "검증 이슈를 찾을 수 없습니다." : code;
};
}
@GetMapping("/{imageId}/file")
public ResponseEntity<Resource> file(
@PathVariable Long issueId,
@PathVariable Long imageId) {
return service.loadFile(issueId, imageId)
.map(resource -> {
String type = service.contentType(issueId, imageId).orElse(MediaType.APPLICATION_OCTET_STREAM_VALUE);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(type))
.header(HttpHeaders.CACHE_CONTROL, "private, max-age=3600")
.body(resource);
})
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{imageId}")
public ResponseEntity<Void> delete(
@PathVariable Long issueId,
@PathVariable Long imageId) {
try {
if (!service.delete(issueId, imageId)) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.noContent().build();
} catch (IOException e) {
return ResponseEntity.internalServerError().build();
}
}
}