88 lines
3.7 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|