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,22 +1,20 @@
package com.back.web7_9_codecrete_be.global.initData;

import java.time.LocalDate;
import java.time.LocalDateTime;

import org.springframework.context.annotation.Profile;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert;
import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertPlace;
import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertPlaceRepository;
import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertRepository;
import com.back.web7_9_codecrete_be.domain.users.entity.SocialType;
import com.back.web7_9_codecrete_be.domain.users.entity.User;
import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository;

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;

@Profile("dev")
@Component
Expand Down Expand Up @@ -51,6 +49,8 @@ private void createTestUser() {
.socialId(null)
.build();

testUser.initSetting();

userRepository.save(testUser);
}

Expand All @@ -69,6 +69,8 @@ private void createAdminUser() {
.socialId(null)
.build();

adminUser.initSetting();

// dev 전용 어드민 권한 부여
adminUser.promoteToAdmin();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.back.web7_9_codecrete_be.global.storage;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class FileDeleteQueue {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String fileUrl;

private LocalDateTime deleteAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.back.web7_9_codecrete_be.global.storage;

import org.springframework.data.jpa.repository.JpaRepository;

import java.time.LocalDateTime;
import java.util.List;

public interface FileDeleteQueueRepository extends JpaRepository<FileDeleteQueue, Long> {
List<FileDeleteQueue> findAllByDeleteAtBefore(LocalDateTime now);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.back.web7_9_codecrete_be.global.storage;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.s3.S3Client;

import java.time.LocalDateTime;
import java.util.List;

@Component
@RequiredArgsConstructor
public class FileDeleteScheduler {

private final FileDeleteQueueRepository repository;
private final S3Client s3Client;

@Value("${cloud.aws.s3.bucket}")
private String bucket;

@Value("${cloud.aws.region.static}")
private String region;

@Scheduled(fixedDelay = 600000) // 10분마다 실행
public void deleteFiles() {

List<FileDeleteQueue> targets =
repository.findAllByDeleteAtBefore(LocalDateTime.now());

for (FileDeleteQueue file : targets) {
try {
String key = extractKey(file.getFileUrl());

s3Client.deleteObject(builder -> builder
.bucket(bucket)
.key(key)
);

} catch (Exception e) {
// 실패해도 계속 진행
}
}

repository.deleteAll(targets);
}

private String extractKey(String fileUrl) {
String prefix = "https://" + bucket + ".s3." + region + ".amazonaws.com/";
return fileUrl.substring(prefix.length());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void validateImageFile(MultipartFile file) {
throw new BusinessException(FileErrorCode.EXTENSION_MISMATCH);
}

String extension = filename.substring(filename.lastIndexOf('.') + 1);
String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();

// 확장자 ↔ MIME 타입 매칭
if (!imageMimeType.matches(extension)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum ImageMimeType {

public static ImageMimeType from(String detectedMimeType) {
return Arrays.stream(values())
.filter(it -> it.mimeType.equals(detectedMimeType))
.filter(it -> detectedMimeType.startsWith(it.mimeType))
.findFirst()
.orElseThrow(() ->
new BusinessException(FileErrorCode.INVALID_IMAGE_TYPE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class S3FileStorageService implements FileStorageService {

private final S3Client s3Client;
private final ImageFileValidator imageFileValidator;
private final FileDeleteQueueRepository fileDeleteQueueRepository;

@Value("${cloud.aws.s3.bucket}")
private String bucket;
Expand All @@ -27,7 +30,16 @@ public class S3FileStorageService implements FileStorageService {
@Override
public String upload(MultipartFile file, String basePath) {

String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
imageFileValidator.validateImageFile(file);

String originalFilename = file.getOriginalFilename();

// 확장자 추출
String extension = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

// 파일명 제거 (UUID만 사용)
String fileName = UUID.randomUUID() + extension;

String key = basePath + "/" + fileName;

try {
Expand Down Expand Up @@ -56,16 +68,11 @@ public void delete(String fileUrl) {
return;
}

String prefix = "https://" + bucket + ".s3." + region + ".amazonaws.com/";
if (!fileUrl.startsWith(prefix)) {
throw new IllegalArgumentException("잘못된 S3 파일 URL입니다.");
}

String key = fileUrl.substring(prefix.length());

s3Client.deleteObject(builder -> builder
.bucket(bucket)
.key(key)
fileDeleteQueueRepository.save(
FileDeleteQueue.builder()
.fileUrl(fileUrl)
.deleteAt(LocalDateTime.now().plusMinutes(30))
.build()
);
}
}
Loading