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
16 changes: 15 additions & 1 deletion src/main/java/com/likelion/picklbe/domain/brand/Brand.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ public enum Brand {
Pattern.compile("(λ†ν˜‘|ν•˜λ‚˜λ‘œ)\\s*마트"),
Pattern.compile("ν•˜λ‚˜λ‘œν΄λŸ½"),
Pattern.compile("hanaro", Pattern.CASE_INSENSITIVE))),
GS_SUPER(
"gs-super",
"GSμˆ˜νΌλ§ˆμΌ“",
"gs_super.png",
List.of(
Pattern.compile("μ§€μ—μŠ€\\s*λ¦¬ν…ŒμΌ"),
Pattern.compile("\\bGS\\s*수퍼", Pattern.CASE_INSENSITIVE),
Pattern.compile("\\bGS\\s*super", Pattern.CASE_INSENSITIVE))),
GS_THE_FRESH(
"gs-the-fresh",
"GSλ”ν”„λ ˆμ‹œ",
"gs_the_fresh.png",
List.of(
Pattern.compile("더\\s*ν”„λ ˆμ‹œ"),
Pattern.compile("\\bGS\\s*the\\s*fresh", Pattern.CASE_INSENSITIVE))),
DEFAULT("default", "기타", null, List.of());

private final String code;
Expand Down Expand Up @@ -122,4 +137,3 @@ public static Brand fromCodeSafe(String code) {
return DEFAULT;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@ public class BrandImageResolver {
@Value("${app.cdn.default-file:mart_default.png}")
private String defaultFile;

/**
* 원문(지점λͺ…/μƒν˜Έλͺ…/λΈŒλžœλ“œλͺ… 포함 κ°€λŠ₯)μ—μ„œ Brand enum을 μΆ”μ •
*/
/** 원문(지점λͺ…/μƒν˜Έλͺ…/λΈŒλžœλ“œλͺ… 포함 κ°€λŠ₯)μ—μ„œ Brand enum을 μΆ”μ • */
public Brand resolveBrand(String raw) {
if (!StringUtils.hasText(raw)) {
return Brand.DEFAULT;
}
return Brand.fromStoreName(raw);
}

/**
* explicitBrand(컬럼) μš°μ„ , μ—†μœΌλ©΄ name(지점λͺ…)으둜 μΆ”μ •
*/
/** explicitBrand(컬럼) μš°μ„ , μ—†μœΌλ©΄ name(지점λͺ…)으둜 μΆ”μ • */
public Brand resolveBrand(String explicitBrand, String name) {
if (StringUtils.hasText(explicitBrand)) {
// fromStoreName κ°€ λΈŒλžœλ“œλͺ…도 νŒŒμ‹±ν•œλ‹€λŠ” μ „μ œ
Expand All @@ -38,38 +34,28 @@ public Brand resolveBrand(String explicitBrand, String name) {
return resolveBrand(name);
}

/**
* Brand μ½”λ“œλ§Œ ν•„μš”ν•  λ•Œ
*/
/** Brand μ½”λ“œλ§Œ ν•„μš”ν•  λ•Œ */
public String resolveBrandCode(String raw) {
return resolveBrand(raw).code();
}

/**
* Brand μ½”λ“œλ§Œ 이미 μžˆλŠ” 경우(예: DB 쑰회)
*/
/** Brand μ½”λ“œλ§Œ 이미 μžˆλŠ” 경우(예: DB 쑰회) */
public String resolveBrandCodeFromCode(String brandCode) {
Brand b = Brand.fromCodeSafe(brandCode); // μ—†μœΌλ©΄ DEFAULT λ°˜ν™˜ν•˜λ„λ‘ enum에 κ΅¬ν˜„λ˜μ–΄ μžˆμ–΄μ•Ό 함
return b.code();
}

/**
* μ›λ¬Έμ—μ„œ λ°”λ‘œ λŒ€ν‘œ 이미지 URL
*/
/** μ›λ¬Έμ—μ„œ λ°”λ‘œ λŒ€ν‘œ 이미지 URL */
public String resolveImageUrl(String raw) {
return imageUrlFor(resolveBrand(raw));
}

/**
* explicitBrand + name λ™μ‹œ κ³ λ €
*/
/** explicitBrand + name λ™μ‹œ κ³ λ € */
public String resolveImageUrl(String explicitBrand, String name) {
return imageUrlFor(resolveBrand(explicitBrand, name));
}

/**
* Brandκ°€ 이미 μžˆλŠ” 경우 이미지 URL
*/
/** Brandκ°€ 이미 μžˆλŠ” 경우 이미지 URL */
public String imageUrlFor(Brand brand) {
// 1) brandκ°€ null/DEFAULT μ΄κ±°λ‚˜ 파일λͺ…이 λΉ„μ–΄μžˆμœΌλ©΄ κΈ°λ³Έ 이미지
String filename =
Expand All @@ -86,25 +72,19 @@ public String imageUrlFor(Brand brand) {
return joinUrl(rtrimSlashes(baseUrl), rtrimSlashes(brandPath), filename);
}

/**
* Brand μ½”λ“œλ‘œ λ°”λ‘œ 이미지 URL (μ½”λ“œλ§Œ λ‚΄λ €λ°›λŠ” API/쿼리 λŒ€μ‘)
*/
/** Brand μ½”λ“œλ‘œ λ°”λ‘œ 이미지 URL (μ½”λ“œλ§Œ λ‚΄λ €λ°›λŠ” API/쿼리 λŒ€μ‘) */
public String imageUrlForCode(String brandCode) {
Brand b = Brand.fromCodeSafe(brandCode);
return imageUrlFor(b);
}

/**
* μ›λ¬Έμ—μ„œ Brand와 이미지 URL/μ½”λ“œλ₯Ό ν•œ λ²ˆμ—
*/
/** μ›λ¬Έμ—μ„œ Brand와 이미지 URL/μ½”λ“œλ₯Ό ν•œ λ²ˆμ— */
public ResolvedBrand resolve(String raw) {
Brand b = resolveBrand(raw);
return new ResolvedBrand(b, imageUrlFor(b), b.code());
}

/**
* explicitBrand + name λ™μ‹œ μž…λ ₯ 버전
*/
/** explicitBrand + name λ™μ‹œ μž…λ ₯ 버전 */
public ResolvedBrand resolve(String explicitBrand, String name) {
Brand b = resolveBrand(explicitBrand, name);
return new ResolvedBrand(b, imageUrlFor(b), b.code());
Expand Down Expand Up @@ -142,11 +122,6 @@ private static String joinUrl(String... parts) {
return sb.toString();
}

/**
* 편의 λ°˜ν™˜ DTO
*/
public record ResolvedBrand(Brand brand, String imageUrl, String code) {

}
/** 편의 λ°˜ν™˜ DTO */
public record ResolvedBrand(Brand brand, String imageUrl, String code) {}
}

Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public class S3Controller {
@Operation(summary = "이미지 μ—…λ‘œλ“œ API", description = "이미지λ₯Ό μ—…λ‘œλ“œν•˜κ³  URL을 λ¦¬ν„΄λ°›λŠ” API")
@PostMapping(value = "/image-upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<BaseResponse<S3Response>> uploadImage(
@RequestParam PathName pathName, MultipartFile file
) {
@RequestParam PathName pathName, MultipartFile file) {

S3Response s3Response = s3Service.uploadImage(pathName, file);
return ResponseEntity.ok(BaseResponse.success("이미지 μ—…λ‘œλ“œμ— μ„±κ³΅ν–ˆμŠ΅λ‹ˆλ‹€.", s3Response));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.likelion.picklbe.global.s3.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.likelion.picklbe.domain.brand.Brand;

import com.amazonaws.services.s3.AmazonS3;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class BrandImagePromotionService {

private final AmazonS3 s3;

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

@Value("${cloud.aws.s3.path.brand:images/brand}")
private String brandPath;

public String promote(String uuidKey, Brand brand) {
if (brand == null || brand.filename() == null) {
throw new IllegalArgumentException("κ³ μ • 파일λͺ…이 μ—†λŠ” λΈŒλžœλ“œμž…λ‹ˆλ‹€: " + brand);
}
String srcKey = trimSlash(brandPath) + "/" + trimSlash(uuidKey);
String dstKey = trimSlash(brandPath) + "/" + brand.filename();

s3.copyObject(bucket, srcKey, bucket, dstKey);
s3.deleteObject(bucket, srcKey);

return dstKey;
}

private String trimSlash(String s) {
return s == null ? "" : s.replaceAll("^/+", "").replaceAll("/+$", "");
}
}
50 changes: 27 additions & 23 deletions src/main/java/com/likelion/picklbe/global/s3/service/S3Service.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package com.likelion.picklbe.global.s3.service;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsV2Request;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.likelion.picklbe.global.config.S3Config;
import com.likelion.picklbe.global.exception.CustomException;
import com.likelion.picklbe.global.s3.dto.S3Response;
import com.likelion.picklbe.global.s3.entity.PathName;
import com.likelion.picklbe.global.s3.exception.S3ErrorCode;
import java.io.ByteArrayInputStream;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.likelion.picklbe.global.config.S3Config;
import com.likelion.picklbe.global.exception.CustomException;
import com.likelion.picklbe.global.s3.dto.S3Response;
import com.likelion.picklbe.global.s3.entity.PathName;
import com.likelion.picklbe.global.s3.exception.S3ErrorCode;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsV2Request;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
Expand Down Expand Up @@ -95,17 +99,17 @@ public String base64UploadFile(PathName pathName, String base64Url) {
public String createKeyName(PathName pathName) {

return switch (pathName) {
case M01 -> s3Config.getM01Folder();
case M02 -> s3Config.getM02Folder();
case M03 -> s3Config.getM03Folder();
case M04 -> s3Config.getM04Folder();
case M05 -> s3Config.getM05Folder();
case M06 -> s3Config.getM06Folder();
case M07 -> s3Config.getM07Folder();
case M08 -> s3Config.getM08Folder();
case MARKET -> s3Config.getMARKETFolder();
case BRAND -> s3Config.getBRANDFolder();
}
case M01 -> s3Config.getM01Folder();
case M02 -> s3Config.getM02Folder();
case M03 -> s3Config.getM03Folder();
case M04 -> s3Config.getM04Folder();
case M05 -> s3Config.getM05Folder();
case M06 -> s3Config.getM06Folder();
case M07 -> s3Config.getM07Folder();
case M08 -> s3Config.getM08Folder();
case MARKET -> s3Config.getMARKETFolder();
case BRAND -> s3Config.getBRANDFolder();
}
+ '/'
+ UUID.randomUUID();
}
Expand Down