Skip to content

Commit ba3f498

Browse files
committed
feat: get presigned video URL logic #160
1 parent d53fa30 commit ba3f498

File tree

3 files changed

+129
-15
lines changed

3 files changed

+129
-15
lines changed

backend/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ dependencies {
3535
// Lombok 의존성 추가
3636
compileOnly 'org.projectlombok:lombok:1.18.30'
3737
annotationProcessor 'org.projectlombok:lombok:1.18.30'
38+
39+
// S3
40+
implementation('com.amazonaws:aws-java-sdk-s3:1.12.543') {
41+
// 기존 취약한 ion-java 제외하고
42+
exclude group: 'software.amazon.ion', module: 'ion-java'
43+
}
3844
}
3945

4046
tasks.named('test') {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.example.backend.config;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import com.amazonaws.auth.AWSCredentialsProvider;
7+
import com.amazonaws.services.s3.AmazonS3;
8+
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
9+
import com.amazonaws.auth.AWSStaticCredentialsProvider;
10+
import com.amazonaws.auth.BasicAWSCredentials;
11+
12+
13+
@Configuration
14+
public class S3Config {
15+
16+
@Bean
17+
public AWSCredentialsProvider awsCredentialsProvider(
18+
@Value("${cloud.aws.credentials.access-key}") String accessKey,
19+
@Value("${cloud.aws.credentials.secret-key}") String secretKey) {
20+
BasicAWSCredentials creds = new BasicAWSCredentials(accessKey, secretKey);
21+
return new AWSStaticCredentialsProvider(creds);
22+
}
23+
24+
@Bean
25+
public AmazonS3 amazonS3(AWSCredentialsProvider awsCredentialsProvider,
26+
@Value("${cloud.aws.region.static}") String region) {
27+
return AmazonS3ClientBuilder.standard()
28+
.withCredentials(awsCredentialsProvider)
29+
.withRegion(region)
30+
.build();
31+
}
32+
}

backend/src/main/java/com/example/backend/dashboard/service/DashboardService.java

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.example.backend.dashboard.service;
22

3+
import com.amazonaws.HttpMethod;
4+
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
35
import com.example.backend.common.domain.CaseEntity;
46
import com.example.backend.common.domain.PoliceEntity;
57
import com.example.backend.dashboard.dto.DashboardResponse;
@@ -10,21 +12,63 @@
1012
import jakarta.persistence.EntityNotFoundException;
1113
import jakarta.servlet.http.HttpSession;
1214
import lombok.RequiredArgsConstructor;
15+
import org.springframework.beans.factory.annotation.Value;
1316
import org.springframework.stereotype.Service;
1417
import org.springframework.transaction.annotation.Transactional;
1518

1619
import java.time.LocalDateTime;
1720
import java.time.format.DateTimeFormatter;
1821
import java.util.*;
22+
import java.util.concurrent.TimeUnit;
1923
import java.util.stream.Collectors;
2024

25+
26+
import com.amazonaws.services.s3.AmazonS3;
27+
28+
2129
@Service
2230
@Transactional
2331
@RequiredArgsConstructor
2432
public class DashboardService {
2533

34+
@Value("${cloud.aws.bucket}")
35+
private String bucket;
36+
private final AmazonS3 s3Client;
2637
private final DashboardRepository dashboardRepository;
2738

39+
40+
public Map<String, String> getCaseVideo(int id, HttpSession session) {
41+
CaseEntity caseEntity = getAuthorizedCase(id, session);
42+
43+
String videoKey = caseEntity.getVideo();
44+
if (videoKey == null || videoKey.trim().isEmpty()) {
45+
throw new EntityNotFoundException("해당 사건에 대한 영상이 없습니다.");
46+
}
47+
48+
if (caseEntity.getState() == CaseEntity.CaseState.미확인) {
49+
caseEntity.setState(CaseEntity.CaseState.확인);
50+
dashboardRepository.save(caseEntity);
51+
}
52+
53+
// Presigned URL 유효기간 설정 (30분)
54+
Date expiration = new Date();
55+
long expTime = expiration.getTime();
56+
expTime += TimeUnit.MINUTES.toMillis(30); // 30 minute
57+
expiration.setTime(expTime);
58+
59+
GeneratePresignedUrlRequest presignRequest =
60+
new GeneratePresignedUrlRequest(bucket, videoKey)
61+
.withMethod(HttpMethod.GET)
62+
.withExpiration(expiration);
63+
64+
String url = s3Client.generatePresignedUrl(presignRequest).toString();
65+
return Collections.singletonMap("video", url);
66+
67+
}
68+
69+
70+
71+
2872
// 세션에서 officeId 추출
2973
private int getAuthenticatedOfficeId(HttpSession session) {
3074
UserResponseDto user = (UserResponseDto) session.getAttribute("user");
@@ -80,22 +124,54 @@ public List<DashboardResponse> getCases(HttpSession session) {
80124
.collect(Collectors.toList());
81125
}
82126

83-
// id별 사건 영상 확인
84-
public Map<String, String> getCaseVideo(int id, HttpSession session) {
85-
CaseEntity caseEntity = getAuthorizedCase(id, session);
86127

87-
String videoUrl = caseEntity.getVideo();
88-
if (videoUrl == null || videoUrl.trim().isEmpty()) {
89-
throw new EntityNotFoundException("해당 사건에 대한 영상이 없습니다.");
90-
}
91-
92-
if (caseEntity.getState() == CaseEntity.CaseState.미확인) {
93-
caseEntity.setState(CaseEntity.CaseState.확인);
94-
dashboardRepository.save(caseEntity);
95-
}
96-
97-
return Collections.singletonMap("video", videoUrl);
98-
}
128+
// public Map<String, String> getCaseVideo(int id, HttpSession session) {
129+
// CaseEntity caseEntity = getAuthorizedCase(id, session);
130+
//
131+
// String videoUrl = caseEntity.getVideo();
132+
// if (videoUrl == null || videoUrl.trim().isEmpty()) {
133+
// throw new EntityNotFoundException("해당 사건에 대한 영상이 없습니다.");
134+
// }
135+
//
136+
// if (caseEntity.getState() == CaseEntity.CaseState.미확인) {
137+
// caseEntity.setState(CaseEntity.CaseState.확인);
138+
// dashboardRepository.save(caseEntity);
139+
// }
140+
// String filename = videoUrl;
141+
//
142+
//
143+
// Date expiration = new Date();
144+
// long expTime = expiration.getTime();
145+
// expTime += TimeUnit.MINUTES.toMillis(30); // 30 minute
146+
// expiration.setTime(expTime);
147+
//
148+
// GetPresignedUrlRequest generatePresignedUrlRequest = new GetPresignedUrlRequest(bucket, fileName)
149+
// .withMethod(HttpMethod.GET)
150+
// .withExpiration(expiration);
151+
//
152+
//
153+
// return Collections.singletonMap("video", AWSS3ResDto.builder()
154+
// .url(s3Presigner.getPresignedUrl(generatePresignedUrlRequest).toString()));
155+
// }
156+
//
157+
158+
159+
160+
// public String getPresignedUrl(String originUrl) {
161+
// Presigned URL 생성
162+
163+
164+
// GetPresignedUrlRequest getPresignedUrlRequest = s3Presigner.presignGetObject(
165+
// req -> req.signatureDuration(Duration.ofMinutes(15)) // 15분 유효기간
166+
// .getObjectRequest(
167+
// GetObjectRequest.builder()
168+
// .bucket(bucketName)
169+
// .key(key)
170+
// .build()
171+
// )
172+
// )
173+
174+
// }
99175

100176
// 출동, 미출동 상태 변경
101177
public Map<String, String> updateCaseState(int id, StateRequest request, HttpSession session) {

0 commit comments

Comments
 (0)