mirror of
https://github.com/won-ktds/smarketing-backend.git
synced 2026-01-22 03:26:24 +00:00
feat: generate poster
This commit is contained in:
parent
4b7f6c11e6
commit
ffa4a7f0a9
@ -13,6 +13,8 @@ import com.won.smarketing.content.presentation.dto.PosterContentCreateRequest;
|
||||
import com.won.smarketing.content.presentation.dto.PosterContentCreateResponse;
|
||||
import com.won.smarketing.content.presentation.dto.PosterContentSaveRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -25,10 +27,14 @@ import java.util.List;
|
||||
* 홍보 포스터 생성 및 저장 기능 구현
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class PosterContentService implements PosterContentUseCase {
|
||||
|
||||
@Value("${azure.storage.container.poster-images:poster-images}")
|
||||
private String posterImageContainer;
|
||||
|
||||
private final ContentRepository contentRepository;
|
||||
private final AiPosterGenerator aiPosterGenerator;
|
||||
private final BlobStorageService blobStorageService;
|
||||
@ -42,11 +48,11 @@ public class PosterContentService implements PosterContentUseCase {
|
||||
@Override
|
||||
@Transactional
|
||||
public PosterContentCreateResponse generatePosterContent(List<MultipartFile> images, PosterContentCreateRequest request) {
|
||||
|
||||
log.info("지점1-1");
|
||||
// 1. 이미지 blob storage에 저장하고 request 저장
|
||||
List<String> imageUrls = blobStorageService.uploadImage(images, "poster-content-original");
|
||||
List<String> imageUrls = blobStorageService.uploadImage(images, posterImageContainer);
|
||||
request.setImages(imageUrls);
|
||||
|
||||
log.info("지점2-1");
|
||||
// 2. AI 요청
|
||||
String generatedPoster = aiPosterGenerator.generatePoster(request);
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ public class SnsContentService implements SnsContentUseCase {
|
||||
@Transactional
|
||||
public SnsContentCreateResponse generateSnsContent(SnsContentCreateRequest request, List<MultipartFile> files) {
|
||||
//파일들 주소 가져옴
|
||||
List<String> urls = blobStorageService.uploadImage(files);
|
||||
List<String> urls = blobStorageService.uploadImage(files, "containerName");
|
||||
request.setImages(urls);
|
||||
|
||||
// AI를 사용하여 SNS 콘텐츠 생성
|
||||
|
||||
@ -17,7 +17,7 @@ public interface BlobStorageService {
|
||||
* @param file 업로드할 파일
|
||||
* @return 업로드된 파일의 URL
|
||||
*/
|
||||
List<String> uploadImage(List<MultipartFile> file);
|
||||
List<String> uploadImage(List<MultipartFile> file, String containerName);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -34,12 +34,6 @@ public class BlobStorageServiceImpl implements BlobStorageService {
|
||||
|
||||
private final BlobServiceClient blobServiceClient;
|
||||
|
||||
@Value("${azure.storage.container.poster-images:poster-images}")
|
||||
private String posterImageContainer;
|
||||
|
||||
@Value("${azure.storage.container.content-images:content-images}")
|
||||
private String contentImageContainer;
|
||||
|
||||
@Value("${azure.storage.max-file-size:10485760}") // 10MB
|
||||
private long maxFileSize;
|
||||
|
||||
@ -60,7 +54,7 @@ public class BlobStorageServiceImpl implements BlobStorageService {
|
||||
* @return 업로드된 파일의 URL
|
||||
*/
|
||||
@Override
|
||||
public List<String> uploadImage(List<MultipartFile> files) {
|
||||
public List<String> uploadImage(List<MultipartFile> files, String containerName) {
|
||||
// 파일 유효성 검증
|
||||
validateImageFile(files);
|
||||
List<String> urls = new ArrayList<>();
|
||||
@ -70,10 +64,10 @@ public class BlobStorageServiceImpl implements BlobStorageService {
|
||||
for(MultipartFile file : files) {
|
||||
String fileName = generateMenuImageFileName(file.getOriginalFilename());
|
||||
|
||||
ensureContainerExists(posterImageContainer);
|
||||
ensureContainerExists(containerName);
|
||||
|
||||
// Blob 클라이언트 생성
|
||||
BlobContainerClient containerClient = blobServiceClient.getBlobContainerClient(posterImageContainer);
|
||||
BlobContainerClient containerClient = blobServiceClient.getBlobContainerClient(containerName);
|
||||
BlobClient blobClient = containerClient.getBlobClient(fileName);
|
||||
|
||||
// 파일 업로드 (간단한 방식)
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.won.smarketing.content.presentation.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.won.smarketing.common.dto.ApiResponse;
|
||||
import com.won.smarketing.content.application.usecase.ContentQueryUseCase;
|
||||
import com.won.smarketing.content.application.usecase.PosterContentUseCase;
|
||||
@ -11,6 +13,7 @@ import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -25,6 +28,7 @@ import java.util.List;
|
||||
* SNS 콘텐츠 생성, 포스터 생성, 콘텐츠 관리 기능 제공
|
||||
*/
|
||||
@Tag(name = "마케팅 콘텐츠 관리", description = "AI 기반 마케팅 콘텐츠 생성 및 관리 API")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/content")
|
||||
@RequiredArgsConstructor
|
||||
@ -33,6 +37,7 @@ public class ContentController {
|
||||
private final SnsContentUseCase snsContentUseCase;
|
||||
private final PosterContentUseCase posterContentUseCase;
|
||||
private final ContentQueryUseCase contentQueryUseCase;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* SNS 게시물 생성
|
||||
@ -70,28 +75,12 @@ public class ContentController {
|
||||
@Operation(summary = "홍보 포스터 생성", description = "AI를 활용하여 홍보 포스터를 생성합니다.")
|
||||
@PostMapping(value = "/poster/generate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public ResponseEntity<ApiResponse<PosterContentCreateResponse>> generatePosterContent(
|
||||
@Parameter(
|
||||
description = "참고할 이미지 파일들 (선택사항, 최대 5개)",
|
||||
required = false,
|
||||
content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
)
|
||||
@Parameter(content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE))
|
||||
@RequestPart(value = "images", required = false) List<MultipartFile> images,
|
||||
@Parameter(
|
||||
description = "포스터 생성 요청 정보",
|
||||
required = true,
|
||||
example = """
|
||||
{
|
||||
"title": "신메뉴 출시 이벤트",
|
||||
"category": "이벤트",
|
||||
"requirement": "밝고 화사한 분위기로 만들어주세요",
|
||||
"eventName": "아메리카노 할인 이벤트",
|
||||
"startDate": "2024-01-15",
|
||||
"endDate": "2024-01-31",
|
||||
"photoStyle": "밝고 화사한"
|
||||
}
|
||||
"""
|
||||
)
|
||||
@RequestPart(value = "request") @Valid PosterContentCreateRequest request) {
|
||||
@RequestPart("request") String requestJson) throws JsonProcessingException {
|
||||
|
||||
// JSON 파싱
|
||||
PosterContentCreateRequest request = objectMapper.readValue(requestJson, PosterContentCreateRequest.class);
|
||||
|
||||
PosterContentCreateResponse response = posterContentUseCase.generatePosterContent(images, request);
|
||||
return ResponseEntity.ok(ApiResponse.success(response, "포스터 콘텐츠가 성공적으로 생성되었습니다."));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user