diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/common/filter/JwtExceptionFilter.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/common/filter/JwtExceptionFilter.kt index 7b3b3a6..d6a6f3a 100644 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/common/filter/JwtExceptionFilter.kt +++ b/lovebird-api/src/main/kotlin/com/lovebird/api/common/filter/JwtExceptionFilter.kt @@ -23,7 +23,7 @@ class JwtExceptionFilter : OncePerRequestFilter() { } fun setErrorResponse(returnCode: ReturnCode, response: HttpServletResponse) { - response.status = HttpStatus.BAD_REQUEST.value() + response.status = HttpStatus.UNAUTHORIZED.value() response.contentType = "application/json; charset=UTF-8" val result: ApiResponse = ApiResponse.fail(returnCode) diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/controller/external/S3ImageController.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/controller/external/S3ImageController.kt index f59c153..de6e927 100644 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/controller/external/S3ImageController.kt +++ b/lovebird-api/src/main/kotlin/com/lovebird/api/controller/external/S3ImageController.kt @@ -2,7 +2,7 @@ package com.lovebird.api.controller.external import com.lovebird.api.annotation.AuthorizedUser import com.lovebird.api.dto.param.external.DiaryImagesUploadParam -import com.lovebird.api.dto.request.external.ProfileImageUploadRequest +import com.lovebird.api.dto.param.external.ProfileImageUploadParam import com.lovebird.api.service.external.S3ImageService import com.lovebird.common.response.ApiResponse import com.lovebird.domain.entity.User @@ -22,10 +22,9 @@ class S3ImageController( @PostMapping("/profile") fun uploadProfileImage( - @RequestPart(value = "image") image: MultipartFile, - @RequestPart(value = "imageUploadRequest") request: ProfileImageUploadRequest + @RequestPart(value = "image") image: MultipartFile ): ApiResponse { - val fileUploadResponse = s3ImageService.uploadProfileImage(request.toParam(image)) + val fileUploadResponse = s3ImageService.uploadProfileImage(ProfileImageUploadParam.from(image)) return ApiResponse.success(fileUploadResponse) } @@ -33,7 +32,7 @@ class S3ImageController( @PostMapping("/diary") fun uploadDiaryImages( @AuthorizedUser user: User, - @RequestPart(value = "images") images: List + @RequestPart(value = "image") images: List ): ApiResponse { val fileUploadListResponse = s3ImageService.uploadDiaryImages(DiaryImagesUploadParam.of(images, user.id!!)) diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/dto/param/external/ProfileImageUploadParam.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/dto/param/external/ProfileImageUploadParam.kt index bdd6867..605e359 100644 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/dto/param/external/ProfileImageUploadParam.kt +++ b/lovebird-api/src/main/kotlin/com/lovebird/api/dto/param/external/ProfileImageUploadParam.kt @@ -1,9 +1,19 @@ package com.lovebird.api.dto.param.external +import com.lovebird.common.enums.Domain import org.springframework.web.multipart.MultipartFile data class ProfileImageUploadParam( val image: MultipartFile, - val domain: String, - val providerId: String -) + val domain: String +) { + companion object { + + fun from(image: MultipartFile): ProfileImageUploadParam { + return ProfileImageUploadParam( + image = image, + domain = Domain.PROFILE.lower() + ) + } + } +} diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/dto/request/external/ProfileImageUploadRequest.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/dto/request/external/ProfileImageUploadRequest.kt deleted file mode 100644 index 6146709..0000000 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/dto/request/external/ProfileImageUploadRequest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.lovebird.api.dto.request.external - -import com.lovebird.api.dto.param.external.ProfileImageUploadParam -import com.lovebird.common.enums.Domain -import org.springframework.web.multipart.MultipartFile - -data class ProfileImageUploadRequest( - val providerId: String -) { - fun toParam(image: MultipartFile): ProfileImageUploadParam { - return ProfileImageUploadParam( - image = image, - domain = Domain.PROFILE.lower(), - providerId = providerId - ) - } -} diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/PresignedUrlService.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/PresignedUrlService.kt index 771ea2e..6936aa6 100644 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/PresignedUrlService.kt +++ b/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/PresignedUrlService.kt @@ -21,7 +21,7 @@ class PresignedUrlService( } fun getProfilePresignedUrl(param: ProfileUploadPresignedUrlParam): PresignedUrlResponse { - val newFilename: String = FilenameUtils.generateProfileImageName(param.filename, param.providerId) + val newFilename: String = FilenameUtils.generateProfileImageName(param.filename) val presignedUrl: String = presignedUrlProvider.getUploadPresignedUrl(Domain.PROFILE.lower(), null, newFilename) return PresignedUrlResponse(presignedUrl, newFilename) diff --git a/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/S3ImageService.kt b/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/S3ImageService.kt index 112b6a9..4fe4f87 100644 --- a/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/S3ImageService.kt +++ b/lovebird-api/src/main/kotlin/com/lovebird/api/service/external/S3ImageService.kt @@ -17,7 +17,7 @@ class S3ImageService( ) { fun uploadProfileImage(param: ProfileImageUploadParam): FileUploadResponse { - val newFileName: String = generateProfileImageName(param.image.originalFilename!!, param.providerId) + val newFileName: String = generateProfileImageName(param.image.originalFilename!!) return fileUploadService.upload(FileUploadRequest(param.image, newFileName, param.domain, null)) } diff --git a/lovebird-api/src/main/resources/application.yml b/lovebird-api/src/main/resources/application.yml index fb738e3..6935a5a 100644 --- a/lovebird-api/src/main/resources/application.yml +++ b/lovebird-api/src/main/resources/application.yml @@ -14,6 +14,10 @@ spring: - fcm.yml - logging-${spring.profiles.default}.yml - monitoring.yml + servlet: + multipart: + max-file-size: 50MB + max-request-size: 50MB apple: test-code: ${APPLE_TEST_CODE} diff --git a/lovebird-api/src/main/resources/static/docs/index.html b/lovebird-api/src/main/resources/static/docs/index.html index 3bc1c83..c6e2c5b 100644 --- a/lovebird-api/src/main/resources/static/docs/index.html +++ b/lovebird-api/src/main/resources/static/docs/index.html @@ -947,8 +947,7 @@

$ curl 'http://localhost:8080/api/v1/images/profile' -i -X POST \
     -H 'Content-Type: application/json;charset=UTF-8' \
-    -F 'image=@image.png;type=image/png' \
-    -F 'imageUploadRequest={"providerId":"provider-id"};type=application/json'
+ -F 'image=@image.png;type=image/png' @@ -965,11 +964,6 @@

@@ -999,8 +993,7 @@

$ http --multipart POST 'http://localhost:8080/api/v1/images/profile' \
     'Content-Type:application/json;charset=UTF-8' \
-    'image'@'image.png' \
-    'imageUploadRequest'='{"providerId":"provider-id"}'
+ 'image'@'image.png' @@ -1013,31 +1006,7 @@

-

5.1.6. Request part-imageuploadrequest-fields

- ----- - - - - - - - - - - - - - - -
PathTypeDescription

providerId

com.lovebird.api.utils.restdocs.STRING@308af0df

소셜 제공자 ID

- -
-

5.1.7. Response body

+

5.1.6. Response body

{
@@ -1052,7 +1021,7 @@ 

-

5.1.8. Response fields

+

5.1.7. Response fields

@@ -1105,7 +1074,7 @@

$ curl 'http://localhost:8080/api/v1/images/diary' -i -X POST \ -H 'Content-Type: multipart/form-data;charset=UTF-8' \ -H 'Authorization: Bearer access-token' \ - -F 'images=image;type=multipart/form-data' + -F 'image=image;type=multipart/form-data' @@ -1119,7 +1088,7 @@

$ http --multipart POST 'http://localhost:8080/api/v1/images/diary' \
     'Authorization:Bearer access-token' \
-    'images'='image'
+ 'image'='image' @@ -2549,8 +2518,8 @@
7.2.1 "imageUrl" : "test-image-url", "email" : "test-email", "nickname" : "test-nickname", - "birthday" : "2024-03-17", - "firstDate" : "2024-03-17", + "birthday" : "2024-03-21", + "firstDate" : "2024-03-21", "gender" : "UNKNOWN" } @@ -4105,7 +4074,7 @@

10.2.1. HTTP request

-
GET /api/v1/diaries/memory-date?memoryDate=2024-03-17 HTTP/1.1
+
GET /api/v1/diaries/memory-date?memoryDate=2024-03-21 HTTP/1.1
 Authorization: Bearer access-token
 Host: localhost:8080
@@ -4169,7 +4138,7 @@

10.3.1. HTTP request

-
GET /api/v1/diaries/cursor?memoryDate=2024-03-17&searchType=BEFORE&diaryId=-1&pageSize=10 HTTP/1.1
+
GET /api/v1/diaries/cursor?memoryDate=2024-03-21&searchType=BEFORE&diaryId=-1&pageSize=10 HTTP/1.1
 Authorization: Bearer access-token
 Host: localhost:8080
@@ -4374,7 +4343,7 @@

@@ -4575,7 +4544,7 @@

{
   "title" : "다이어리 제목",
-  "memoryDate" : "2024-03-17",
+  "memoryDate" : "2024-03-21",
   "place" : "장소",
   "content" : "내용",
   "imageUrls" : [ "imageUrl1", "imageUrl2" ]
@@ -4819,7 +4788,7 @@ 

{
   "title" : "다이어리 제목 수정",
-  "memoryDate" : "2024-03-17",
+  "memoryDate" : "2024-03-21",
   "place" : "장소",
   "content" : "내용 수정",
   "imageUrls" : [ "imageUrl1", "imageUrl2" ]
@@ -5016,7 +4985,7 @@ 

diff --git a/lovebird-api/src/test/kotlin/com/lovebird/api/controller/external/S3ImageControllerTest.kt b/lovebird-api/src/test/kotlin/com/lovebird/api/controller/external/S3ImageControllerTest.kt index 11150ff..17bf2dd 100644 --- a/lovebird-api/src/test/kotlin/com/lovebird/api/controller/external/S3ImageControllerTest.kt +++ b/lovebird-api/src/test/kotlin/com/lovebird/api/controller/external/S3ImageControllerTest.kt @@ -1,7 +1,6 @@ package com.lovebird.api.controller.external import com.lovebird.api.common.base.ControllerDescribeSpec -import com.lovebird.api.dto.request.external.ProfileImageUploadRequest import com.lovebird.api.service.external.S3ImageService import com.lovebird.api.utils.CommonTestFixture.getMultipartFile import com.lovebird.api.utils.restdocs.ARRAY @@ -23,8 +22,6 @@ import org.springframework.http.MediaType import org.springframework.mock.web.MockMultipartFile import org.springframework.restdocs.ManualRestDocumentation import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.multipart -import org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath -import org.springframework.restdocs.payload.PayloadDocumentation.requestPartFields import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.web.context.WebApplicationContext @@ -48,32 +45,19 @@ class S3ImageControllerTest( context("유효한 요청이 전달되면") { val image = getMultipartFile() - val imageUploadRequest = ProfileImageUploadRequest("provider-id") val response = FileUploadResponse("1-profile.png", "프로필 이미지 url") val request = multipart(url) .file(image) - .file( - MockMultipartFile( - "imageUploadRequest", - "", - "application/json", - toJson(imageUploadRequest).toByteArray() - ) - ) .contentType(MediaType.APPLICATION_JSON) it("1000 SUCCESS") { - every { s3ImageService.uploadProfileImage(imageUploadRequest.toParam(image)) } returns response + every { s3ImageService.uploadProfileImage(any()) } returns response mockMvc .perform(request) .andExpect(status().isOk) .andDocument( "1000-profile-image-upload", - requestPartFields( - "imageUploadRequest", - fieldWithPath("providerId").type(STRING).description("소셜 제공자 ID") - ), envelopeResponseBody( "data.fileName" type STRING means "새로운 파일 이름", "data.fileUrl" type STRING means "파일 URL" @@ -97,7 +81,7 @@ class S3ImageControllerTest( val request = multipart(url) .file( MockMultipartFile( - "images", + "image", "", "multipart/form-data", image.inputStream diff --git a/lovebird-api/src/test/kotlin/com/lovebird/api/service/external/PresignedUrlServiceTest.kt b/lovebird-api/src/test/kotlin/com/lovebird/api/service/external/PresignedUrlServiceTest.kt index 30e2073..ff2fc69 100644 --- a/lovebird-api/src/test/kotlin/com/lovebird/api/service/external/PresignedUrlServiceTest.kt +++ b/lovebird-api/src/test/kotlin/com/lovebird/api/service/external/PresignedUrlServiceTest.kt @@ -8,6 +8,7 @@ import com.lovebird.api.dto.response.external.PresignedUrlResponse import com.lovebird.common.enums.Domain import com.lovebird.s3.provider.PresignedUrlProvider import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe import io.mockk.clearMocks import io.mockk.every import io.mockk.mockk @@ -27,18 +28,17 @@ class PresignedUrlServiceTest : ServiceDescribeSpec({ val filename = "test.png" val domain = Domain.PROFILE val presignedUrl = "https://cdn.lovebird.com/profile/1-profile.png" - val newFilename = "provider-profile.png" context("정상적인 Parameter가 주어졌을 때") { val param = ProfileUploadPresignedUrlParam(providerId, filename) - every { presignedUrlProvider.getUploadPresignedUrl(domain.lower(), null, newFilename) } returns presignedUrl + every { presignedUrlProvider.getUploadPresignedUrl(domain.lower(), null, any()) } returns presignedUrl it("프로필 사진 업로드용 presigned url을 반환한다.") { val response: PresignedUrlResponse = presignedUrlService.getProfilePresignedUrl(param) - response.presignedUrl shouldBe presignedUrl - response.filename shouldBe newFilename + response.presignedUrl shouldNotBe null + response.filename shouldNotBe null } } } diff --git a/lovebird-common/src/main/kotlin/com/lovebird/common/util/FilenameUtils.kt b/lovebird-common/src/main/kotlin/com/lovebird/common/util/FilenameUtils.kt index 25a94e6..a70535d 100644 --- a/lovebird-common/src/main/kotlin/com/lovebird/common/util/FilenameUtils.kt +++ b/lovebird-common/src/main/kotlin/com/lovebird/common/util/FilenameUtils.kt @@ -4,14 +4,15 @@ import com.lovebird.common.util.RandomUtils.generateTimeBasedUUID object FilenameUtils { - fun generateProfileImageName(imageName: String, providerId: String): String { - return "%s-profile%s".format(providerId, getFileExtension(imageName)) + fun generateProfileImageName(imageName: String): String { + val uuid: String = generateTimeBasedUUID() + return "%s-profile%s".format(uuid, getFileExtension(imageName)) } fun generateDiaryImageNames(imageNames: List, userId: Long): List { - val diaryUUID: String = generateTimeBasedUUID() + val uuid: String = generateTimeBasedUUID() var i = 1 - return imageNames.map { "%d_%s-%d%s".format(userId, diaryUUID, i++, getFileExtension(it)) } + return imageNames.map { "%d-%s-%d%s".format(userId, uuid, i++, getFileExtension(it)) } } private fun getFileExtension(originalFileName: String): String { diff --git a/lovebird-external/s3/src/main/kotlin/com/lovebird/s3/service/FileUploadService.kt b/lovebird-external/s3/src/main/kotlin/com/lovebird/s3/service/FileUploadService.kt index 321183d..5fd676a 100644 --- a/lovebird-external/s3/src/main/kotlin/com/lovebird/s3/service/FileUploadService.kt +++ b/lovebird-external/s3/src/main/kotlin/com/lovebird/s3/service/FileUploadService.kt @@ -61,9 +61,9 @@ class FileUploadService( private fun getPath(userId: Long?, domain: String, filename: String): String { return if (userId == null) { - "users/%s/%s".format(domain, filename) + "%s/%s".format(domain, filename) } else { - "users/%s/%n/%s".format(domain, userId, filename) + "%s/%d/%s".format(domain, userId, filename) } } }