Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public enum EventErrorStatus implements BaseCode {
GROUP_CREATE_FAILED(HttpStatus.BAD_REQUEST, "EVENT-0200", "이벤트 그룹 생성 중 오류가 발생했습니다."),
GROUP_COUNT_MISMATCH(HttpStatus.BAD_REQUEST, "EVENT-0201", "그룹 수가 이벤트 설정과 일치하지 않습니다."),
GROUP_NOT_FOUND(HttpStatus.NOT_FOUND, "EVENT-0202", "존재하지 않는 그룹입니다."),
GROUP_NOT_BELONGS_TO_EVENT(HttpStatus.BAD_REQUEST, "EVENT-0203", "해당 그룹은 지정된 이벤트에 속하지 않습니다.")
GROUP_NOT_BELONGS_TO_EVENT(HttpStatus.BAD_REQUEST, "EVENT-0203", "해당 그룹은 지정된 이벤트에 속하지 않습니다."),


;
SUPPORTED_NOT_TYPE(HttpStatus.BAD_REQUEST,"FILE-5000","해당 유형은 지원되지 않는 파일 유형입니다." ),
FILE_NOT_FOUND(HttpStatus.NOT_FOUND,"FILE_4000","해당 파일은 존재하지 않습니다.");

private final HttpStatus httpStatus;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.server.eventee.domain.file.controller;

import com.server.eventee.domain.file.dto.FileRequest;
import com.server.eventee.domain.file.dto.FileUploadResponse;
import com.server.eventee.domain.file.service.FileService;
import com.server.eventee.domain.member.dto.MemberProfileImageDto;
import com.server.eventee.domain.member.dto.MemberProfileImageDto.PresignedUrlResponse;
import com.server.eventee.domain.member.model.Member;
import com.server.eventee.global.exception.BaseResponse;
import com.server.eventee.global.exception.codes.SuccessCode;
import com.server.eventee.global.filter.CurrentMember;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "File", description = "이미지 관련 API")
@RestController
@Validated
@RequiredArgsConstructor
@RequestMapping("/api/v1/file")
public class FileController {
private final FileService fileService;

@Operation(
summary = "이미지 Presigned URL 발급 (PUT)",
description = """
S3에 직접 PUT 업로드할 URL을 발급합니다.
프론트는 해당 URL로 이미지를 업로드한 뒤 /confirm을 호출해야 합니다.
"""
)
@PostMapping("/presigned-url")
public BaseResponse<FileUploadResponse> createPresignedUrl(
@CurrentMember Member member,
@Valid @RequestBody FileRequest.FileUploadRequest request) {

FileUploadResponse response = fileService.createPresignedUrl(request);
return BaseResponse.of(SuccessCode.SUCCESS, response);
}

//업로드 확정 (PUT 완료 후 호출)
@Operation(
summary = "프로필 이미지 업로드 확정",
description = "PUT 업로드가 완료된 이미지를 확인하고 회원 프로필에 반영합니다."
)
@PostMapping("/confirm")
public BaseResponse<String> confirmProfileImage(
@CurrentMember Member member,
@Valid @RequestBody FileRequest.FileConfirmRequest request) {

String imageUrl = fileService.confirmUpload(member, request);
return BaseResponse.of(SuccessCode.SUCCESS, imageUrl);
}

//프로필 이미지 삭제
@Operation(
summary = "프로필 이미지 삭제",
description = "S3에서 기존 프로필 이미지를 삭제하고 회원 프로필을 초기화합니다."
)
@DeleteMapping("/profile-image")
public BaseResponse<String> deleteProfileImage(
@CurrentMember Member member,
@Valid @RequestBody FileRequest.FileDeleteRequest request) {

fileService.deleteFile(request);
return BaseResponse.of(SuccessCode.SUCCESS, "success");
}

}
71 changes: 71 additions & 0 deletions src/main/java/com/server/eventee/domain/file/dto/FileRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.server.eventee.domain.file.dto;


import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

public class FileRequest {

/* -----------------------------------------------------
Presigned URL 발급 요청 (PUT 업로드 Intent)
type: PROFILE / GROUP / EVENT / POST / COMMENT
refId: 어떤 엔티티의 이미지인지
----------------------------------------------------- */
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class FileUploadRequest {

@NotNull
private String type;

@NotNull
private Long refId;

@NotNull
private String contentType;

@NotNull
private Long contentLength;
}

/* -----------------------------------------------------
업로드 확정 요청 (/confirm)
fileUrl: S3 공개 URL
----------------------------------------------------- */
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class FileConfirmRequest {

@NotNull
private String type;

@NotNull
private Long refId;

@NotNull
private String fileUrl;
}

/* -----------------------------------------------------
파일 삭제 요청
----------------------------------------------------- */
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class FileDeleteRequest {

@NotNull
private String type;

@NotNull
private Long refId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.server.eventee.domain.file.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FileUploadResponse {

private String presignedUrl;
private String publicUrl;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.server.eventee.domain.file.service;

import com.server.eventee.domain.file.dto.FileRequest.FileConfirmRequest;
import com.server.eventee.domain.file.dto.FileRequest.FileDeleteRequest;
import com.server.eventee.domain.file.dto.FileRequest.FileUploadRequest;
import com.server.eventee.domain.file.dto.FileUploadResponse;
import com.server.eventee.domain.member.model.Member;

public interface FileService {

FileUploadResponse createPresignedUrl(FileUploadRequest request);

String confirmUpload(Member member,FileConfirmRequest request);

void deleteFile(FileDeleteRequest request);
}
Loading