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
@@ -1,5 +1,10 @@
package org.fontory.fontorybe.file.adapter.inbound;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.servlet.http.HttpServletRequest;
import org.fontory.fontorybe.authentication.adapter.inbound.Login;
import org.fontory.fontorybe.authentication.adapter.inbound.OAuth2;
Expand All @@ -9,6 +14,7 @@
import org.fontory.fontorybe.file.domain.FileCreate;
import org.fontory.fontorybe.file.domain.FileDetails;
import org.fontory.fontorybe.provide.domain.Provide;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
Expand All @@ -20,6 +26,8 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

import static org.fontory.fontorybe.file.validator.MultipartFileValidator.*;

@Slf4j
Expand All @@ -43,18 +51,30 @@ private void logFileDetails(MultipartFile file, String context) {
file.getContentType());
}

@PostMapping("/profile-image")

@Operation(summary = "프로필 이미지 업로드")
@PostMapping(value = "/profile-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> uploadMemberProfileImage(
@OAuth2 Provide provide,
HttpServletRequest request
// @RequestPart MultipartFile file
@Parameter(
description = "업로드할 파일. 정확히 1개의 파일만 제공되어야 합니다.",
required = true,
content = @Content(
mediaType = MediaType.MULTIPART_FORM_DATA_VALUE,
array = @ArraySchema(
schema = @Schema(type = "string", format = "binary"),
maxItems = 1
)
)
)
@RequestPart("file") List<MultipartFile> files
) {
MultipartFile file = extractSingleMultipartFile(request);
MultipartFile file = extractSingleMultipartFile(files);

log.info("Request received: Upload new profile image for oauth provider: {}, provideId: {}",
log.info("Request received: Upload new profile image for oauth provider: {}, provideId: {}",
provide.getProvider(), provide.getId());
logFileDetails(file, "New profile image upload");

FileCreate fileCreate = fileRequestMapper.toProfileImageFileCreate(file, provide);
FileDetails fileDetails = fileService.uploadProfileImage(fileCreate);

Expand All @@ -65,14 +85,25 @@ public ResponseEntity<?> uploadMemberProfileImage(
.body(FileUploadResponse.from(fileDetails));
}

@PutMapping("/profile-image")
@Operation(summary = "프로필 이미지 업데이트")
@PutMapping(value = "/profile-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> uploadMemberProfileImage(
@Login UserPrincipal userPrincipal,
HttpServletRequest request
// @RequestPart MultipartFile file
@Parameter(
description = "업로드할 파일. 정확히 1개의 파일만 제공되어야 합니다.",
required = true,
content = @Content(
mediaType = MediaType.MULTIPART_FORM_DATA_VALUE,
array = @ArraySchema(
schema = @Schema(type = "string", format = "binary"),
maxItems = 1
)
)
)
@RequestPart("file") List<MultipartFile> files
) {
Long memberId = userPrincipal.getId();
MultipartFile file = extractSingleMultipartFile(request);
MultipartFile file = extractSingleMultipartFile(files);

log.info("Request received: Update profile image for member ID: {}", memberId);
logFileDetails(file, "Profile image update");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
package org.fontory.fontorybe.file.validator;

import jakarta.servlet.http.HttpServletRequest;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.fontory.fontorybe.file.domain.exception.SingleFileRequiredException;
import org.fontory.fontorybe.file.domain.exception.InvalidMultipartRequestException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.util.List;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MultipartFileValidator {
public static MultipartFile extractSingleMultipartFile(HttpServletRequest request) {
if (!(request instanceof MultipartHttpServletRequest multipartRequest)) {
log.error("Invalid request: Not a multipart request.");
throw new InvalidMultipartRequestException();
public static MultipartFile extractSingleMultipartFile(List<MultipartFile> files) {
if (files == null || files.isEmpty()) {
log.error("No file uploaded. Exactly one file must be provided.");
throw new SingleFileRequiredException();
}

log.debug("Multipart request received.");
List<MultipartFile> files = multipartRequest.getFiles("file");
log.info("Number of files received: {}", files.size());

if (files.size() != 1) {
log.error("Invalid file count: {}. Exactly one file must be uploaded.", files.size());
throw new SingleFileRequiredException();
}

MultipartFile file = files.get(0);

if (file.isEmpty()) {
log.error("Uploaded file is empty.");
throw new SingleFileRequiredException();
}

log.info("Single file extracted successfully: filename={}, size={} bytes",
file.getOriginalFilename(), file.getSize());
return file;
Expand Down