Skip to content

Commit de4c4f1

Browse files
fix: require filename and filetype
1 parent 184251b commit de4c4f1

4 files changed

Lines changed: 57 additions & 54 deletions

File tree

src/main/java/com/_oormthon/seasonthon/domain/s3/controller/S3Controller.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.springframework.security.core.annotation.AuthenticationPrincipal;
77

88
import com._oormthon.seasonthon.domain.member.entity.User;
9+
import com._oormthon.seasonthon.domain.s3.dto.PresignedUrlResponse;
910
import com._oormthon.seasonthon.domain.s3.service.S3Service;
1011

1112
@RestController
@@ -19,19 +20,22 @@ public class S3Controller {
1920
* 업로드용 Presigned URL 발급
2021
* 프론트에서 파일 업로드 전에 요청
2122
*/
22-
@GetMapping("/presigned-upload")
23-
public ResponseEntity<String> getPresignedUploadUrl(
24-
@AuthenticationPrincipal User user) {
25-
String presignedUrl = s3Service.generateUploadPresignedUrl(user.getUserId());
26-
return ResponseEntity.ok(presignedUrl);
23+
@PostMapping("/presigned")
24+
public ResponseEntity<PresignedUrlResponse> getPresignedUploadUrl(
25+
@AuthenticationPrincipal User user,
26+
@RequestParam String fileName,
27+
@RequestParam String fileType) {
28+
29+
PresignedUrlResponse response = s3Service.generateUploadPresignedUrl(user.getUserId(), fileName, fileType);
30+
return ResponseEntity.ok(response);
2731
}
2832

2933
/**
3034
* 이미지 삭제 (서버가 직접 삭제 요청)
3135
*/
3236
@DeleteMapping("/file")
33-
public ResponseEntity<Void> deleteImage(@RequestParam Long userId) {
34-
s3Service.deleteFile(userId);
37+
public ResponseEntity<Void> deleteImage(@AuthenticationPrincipal User user, @RequestParam String fileName) {
38+
s3Service.deleteFile(user.getUserId(), fileName);
3539
return ResponseEntity.noContent().build();
3640
}
3741
}

src/main/java/com/_oormthon/seasonthon/domain/s3/dto/FileDownloadRequest.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com._oormthon.seasonthon.domain.s3.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@AllArgsConstructor
8+
public class PresignedUrlResponse {
9+
private String uploadUrl;
10+
private String key;
11+
}

src/main/java/com/_oormthon/seasonthon/domain/s3/service/S3Service.java

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com._oormthon.seasonthon.domain.member.dto.res.UserResponse;
88
import com._oormthon.seasonthon.domain.member.service.UserService;
9+
import com._oormthon.seasonthon.domain.s3.dto.PresignedUrlResponse;
910

1011
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
1112
import software.amazon.awssdk.regions.Region;
@@ -30,42 +31,34 @@ public class S3Service {
3031
/**
3132
* S3 Presigned URL (PUT) 발급
3233
*/
33-
public String generateUploadPresignedUrl(Long userId) {
34+
public PresignedUrlResponse generateUploadPresignedUrl(Long userId, String fileName, String fileType) {
3435
UserResponse user = userService.getUserById(userId);
3536

36-
// URL에서 파일명만 추출
37-
String profileImageName = extractFileNameFromUrl(user.profileImage());
38-
3937
// 고유한 S3 키 생성 (닉네임/UUID-파일명)
40-
String key = user.nickname() + "/" + UUID.randomUUID() + "-" + profileImageName;
41-
42-
// 확장자 기반 Content-Type 결정
43-
String contentType = determineContentTypeFromKey(profileImageName);
38+
String key = user.nickname() + "/" + UUID.randomUUID() + "-" + fileName;
4439

4540
// Presigned URL 발급용 요청 생성
4641
PutObjectRequest objectRequest = PutObjectRequest.builder()
4742
.bucket(bucket)
4843
.key(key)
49-
.contentType(contentType)
44+
.contentType(fileType)
5045
.build();
5146

5247
// Presigned URL 생성
5348
PresignedPutObjectRequest presignedRequest = s3Presigner.presignPutObject(
5449
r -> r.putObjectRequest(objectRequest)
5550
.signatureDuration(Duration.ofMinutes(10)));
5651

57-
return presignedRequest.url().toString();
52+
// JSON 형태로 리턴
53+
return new PresignedUrlResponse(presignedRequest.url().toString(), key);
5854
}
5955

6056
/**
6157
* S3 객체 삭제
6258
*/
63-
public void deleteFile(Long userId) {
64-
UserResponse user = userService.getUserById(userId);
59+
public void deleteFile(Long userId, String fileName) {
6560

66-
// URL에서 파일명만 추출
67-
String profileImageName = extractFileNameFromUrl(user.profileImage());
68-
String key = user.nickname() + "/" + profileImageName;
61+
String key = userService.getUserById(userId).nickname() + "/" + fileName;
6962

7063
S3Client s3 = S3Client.builder()
7164
.region(Region.AP_NORTHEAST_2)
@@ -81,37 +74,37 @@ public void deleteFile(Long userId) {
8174
/**
8275
* 파일명에서 Content-Type 추론
8376
*/
84-
private String determineContentTypeFromKey(String key) {
85-
if (key == null)
86-
return "application/octet-stream"; // 기본값
87-
88-
String lowerKey = key.toLowerCase();
89-
90-
if (lowerKey.endsWith(".jpg") || lowerKey.endsWith(".jpeg"))
91-
return "image/jpeg";
92-
if (lowerKey.endsWith(".png"))
93-
return "image/png";
94-
if (lowerKey.endsWith(".gif"))
95-
return "image/gif";
96-
if (lowerKey.endsWith(".webp"))
97-
return "image/webp";
98-
if (lowerKey.endsWith(".svg"))
99-
return "image/svg+xml";
100-
101-
return "application/octet-stream"; // 모르는 확장자일 경우
102-
}
77+
// private String determineContentTypeFromKey(String key) {
78+
// if (key == null)
79+
// return "application/octet-stream"; // 기본값
80+
81+
// String lowerKey = key.toLowerCase();
82+
83+
// if (lowerKey.endsWith(".jpg") || lowerKey.endsWith(".jpeg"))
84+
// return "image/jpeg";
85+
// if (lowerKey.endsWith(".png"))
86+
// return "image/png";
87+
// if (lowerKey.endsWith(".gif"))
88+
// return "image/gif";
89+
// if (lowerKey.endsWith(".webp"))
90+
// return "image/webp";
91+
// if (lowerKey.endsWith(".svg"))
92+
// return "image/svg+xml";
93+
94+
// return "application/octet-stream"; // 모르는 확장자일 경우
95+
// }
10396

10497
/**
10598
* URL에서 파일명만 추출
10699
* 예: https://t1.kakaocdn.net/account_images/default_profile.jpeg →
107100
* default_profile.jpeg
108101
*/
109-
private String extractFileNameFromUrl(String url) {
110-
if (url == null)
111-
return "unknown";
112-
int lastSlash = url.lastIndexOf('/');
113-
if (lastSlash == -1 || lastSlash == url.length() - 1)
114-
return "unknown";
115-
return url.substring(lastSlash + 1);
116-
}
102+
// private String extractFileNameFromUrl(String url) {
103+
// if (url == null)
104+
// return "unknown";
105+
// int lastSlash = url.lastIndexOf('/');
106+
// if (lastSlash == -1 || lastSlash == url.length() - 1)
107+
// return "unknown";
108+
// return url.substring(lastSlash + 1);
109+
// }
117110
}

0 commit comments

Comments
 (0)