11package com .dmu .debug_visual .file_upload ;
22
3+ import com .dmu .debug_visual .file_upload .dto .FileContentResponse ;
34import com .dmu .debug_visual .file_upload .dto .FileResponseDTO ;
45import com .dmu .debug_visual .file_upload .dto .UserFileDTO ;
56import com .dmu .debug_visual .file_upload .service .FileService ;
2122import java .io .IOException ;
2223import java .util .List ;
2324
24- @ Tag (name = "파일 관리 API" , description = "S3 파일 생성, 수정(덮어쓰기) 및 사용자별 파일 목록 조회를 제공합니다." )
25+ @ Tag (name = "파일 관리 API" , description = "S3 파일 생성, 수정, 조회 및 삭제 기능을 제공합니다." )
2526@ RestController
2627@ RequiredArgsConstructor
27- @ RequestMapping ("/api/file" ) // 경로를 단수로 통일
28+ @ RequestMapping ("/api/file" )
2829public class FileController {
2930
3031 private final FileService fileService ;
3132
33+ // =================================================================================
34+ // == 1. 파일 생성 및 수정 (Create & Update)
35+ // =================================================================================
36+
3237 @ Operation (summary = "파일 저장 또는 수정 (덮어쓰기)" ,
3338 description = "form-data로 파일을 업로드합니다. `fileUUID` 파라미터 유무에 따라 동작이 달라집니다.\n \n " +
3439 "- **`fileUUID`가 없으면**: 신규 파일로 저장하고 새로운 `fileUUID`를 발급합니다.\n " +
3540 "- **`fileUUID`가 있으면**: 해당 `fileUUID`를 가진 기존 파일을 덮어씁니다." )
3641 @ ApiResponses ({
37- @ ApiResponse (responseCode = "200" , description = "요청 성공 (생성 또는 수정 완료)" ,
38- content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = FileResponseDTO .class ))),
39- @ ApiResponse (responseCode = "401" , description = "인증 실패 (JWT 토큰 누락 또는 유효하지 않음)" , content = @ Content ),
40- @ ApiResponse (responseCode = "403" , description = "권한 없음 (타인의 파일 수정을 시도)" , content = @ Content ),
41- @ ApiResponse (responseCode = "404" , description = "존재하지 않는 `fileUUID`로 수정 요청" , content = @ Content )
42+ @ ApiResponse (responseCode = "200" , description = "요청 성공" , content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = FileResponseDTO .class ))),
43+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
44+ @ ApiResponse (responseCode = "403" , description = "권한 없음" ),
45+ @ ApiResponse (responseCode = "404" , description = "존재하지 않는 `fileUUID`로 수정 요청" )
4246 })
4347 @ PostMapping (value = "/upload" , consumes = MediaType .MULTIPART_FORM_DATA_VALUE )
4448 public ResponseEntity <FileResponseDTO > uploadOrUpdateFile (
45- @ Parameter (description = "업로드할 파일" )
46- @ RequestParam ("file" ) MultipartFile file ,
47-
48- @ Parameter (description = "수정할 파일의 고유 ID. 신규 업로드 시에는 생략합니다." )
49- @ RequestParam (value = "fileUUID" , required = false ) String fileUUID ,
50-
49+ @ Parameter (description = "업로드할 파일" ) @ RequestParam ("file" ) MultipartFile file ,
50+ @ Parameter (description = "수정할 파일의 고유 ID. 신규 업로드 시에는 생략합니다." ) @ RequestParam (value = "fileUUID" , required = false ) String fileUUID ,
5151 @ AuthenticationPrincipal CustomUserDetails userDetails ) throws IOException {
5252
53- // CustomUserDetails에서 사용자 ID (Long 타입)를 가져오는 메소드가 있다고 가정합니다.
54- // 예: userDetails.getId()
5553 String currentUserId = userDetails .getUsername ();
56-
5754 FileResponseDTO fileResponse = fileService .saveOrUpdateFile (fileUUID , file , currentUserId );
5855 return ResponseEntity .ok (fileResponse );
5956 }
6057
58+ // =================================================================================
59+ // == 2. 파일 조회 (Read)
60+ // =================================================================================
61+
6162 @ Operation (summary = "내 파일 목록 조회" , description = "현재 로그인한 사용자가 생성한 모든 파일의 목록을 조회합니다." )
6263 @ ApiResponses ({
63- @ ApiResponse (responseCode = "200" , description = "조회 성공" ,
64- content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = UserFileDTO .class ))),
65- @ ApiResponse (responseCode = "401" , description = "인증 실패 (JWT 토큰 누락 또는 유효하지 않음)" , content = @ Content )
64+ @ ApiResponse (responseCode = "200" , description = "조회 성공" , content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = UserFileDTO .class ))),
65+ @ ApiResponse (responseCode = "401" , description = "인증 실패" )
6666 })
6767 @ GetMapping ("/my" )
68- public ResponseEntity <List <UserFileDTO >> getMyFiles (
69- @ AuthenticationPrincipal CustomUserDetails userDetails ) {
70-
68+ public ResponseEntity <List <UserFileDTO >> getMyFiles (@ AuthenticationPrincipal CustomUserDetails userDetails ) {
7169 String currentUserId = userDetails .getUsername ();
7270 List <UserFileDTO > myFiles = fileService .getUserFiles (currentUserId );
7371 return ResponseEntity .ok (myFiles );
7472 }
75- }
73+
74+ @ Operation (summary = "파일 내용 조회" , description = "특정 파일의 내용을 조회합니다. 본인의 파일만 조회할 수 있습니다." )
75+ @ ApiResponses ({
76+ @ ApiResponse (responseCode = "200" , description = "조회 성공" , content = @ Content (schema = @ Schema (implementation = FileContentResponse .class ))),
77+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
78+ @ ApiResponse (responseCode = "403" , description = "접근 권한 없음" ),
79+ @ ApiResponse (responseCode = "404" , description = "파일을 찾을 수 없음" )
80+ })
81+ @ GetMapping ("/{fileUUID}/content" )
82+ public ResponseEntity <FileContentResponse > getFileContent (
83+ @ Parameter (description = "내용을 조회할 파일의 고유 ID" ) @ PathVariable String fileUUID ,
84+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
85+ FileContentResponse response = fileService .getFileContent (fileUUID , userDetails .getUsername ());
86+ return ResponseEntity .ok (response );
87+ }
88+
89+ // =================================================================================
90+ // == 3. 파일 삭제 (Delete)
91+ // =================================================================================
92+
93+ @ Operation (summary = "파일 삭제" , description = "특정 파일을 S3와 DB에서 모두 삭제합니다. 본인의 파일만 삭제할 수 있습니다." )
94+ @ ApiResponses ({
95+ @ ApiResponse (responseCode = "200" , description = "삭제 성공" ),
96+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
97+ @ ApiResponse (responseCode = "403" , description = "삭제 권한 없음" ),
98+ @ ApiResponse (responseCode = "404" , description = "파일을 찾을 수 없음" )
99+ })
100+ @ DeleteMapping ("/{fileUUID}" )
101+ public ResponseEntity <Void > deleteFile (
102+ @ Parameter (description = "삭제할 파일의 고유 ID" ) @ PathVariable String fileUUID ,
103+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
104+ fileService .deleteFile (fileUUID , userDetails .getUsername ());
105+ return ResponseEntity .ok ().build ();
106+ }
107+ }
108+
0 commit comments