Merge branch 'be/refactor/image' into 'be/develop'
Fix: Zip파일 업로드 오류 해결 See merge request s11-s-project/S11P21S002!232
This commit is contained in:
commit
b94420a91f
@ -19,7 +19,7 @@ public class Image extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "project_image_id", nullable = false)
|
@Column(name = "project_image_id", nullable = false)
|
||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,10 +11,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@ -27,15 +28,15 @@ public class ImageAsyncService {
|
|||||||
private final ImageRepository imageRepository;
|
private final ImageRepository imageRepository;
|
||||||
private final ThreadPoolTaskExecutor imageUploadExecutor;
|
private final ThreadPoolTaskExecutor imageUploadExecutor;
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Async("imageUploadExecutor")
|
@Async("imageUploadExecutor")
|
||||||
public CompletableFuture<Void> asyncImageUpload(final List<MultipartFile> imageList, final Folder folder, final Integer projectId) {
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
|
public CompletableFuture<Void> asyncImageUpload(final List<MultipartFile> imageFileList, final Folder folder, final Integer projectId) {
|
||||||
log.debug("현재 스레드 - {} 업로드 파일 개수 - {}, 현재 작업 큐 용량 - {}",
|
log.debug("현재 스레드 - {} 업로드 파일 개수 - {}, 현재 작업 큐 용량 - {}",
|
||||||
Thread.currentThread().getName(),
|
Thread.currentThread().getName(),
|
||||||
imageList.size(),
|
imageFileList.size(),
|
||||||
imageUploadExecutor.getThreadPoolExecutor().getQueue().size()); // 큐에 쌓인 작업 수 출력);
|
imageUploadExecutor.getThreadPoolExecutor().getQueue().size()); // 큐에 쌓인 작업 수 출력);
|
||||||
|
|
||||||
imageList.forEach(file -> {
|
imageFileList.forEach(file -> {
|
||||||
try{
|
try{
|
||||||
String extension = getExtension(file.getOriginalFilename());
|
String extension = getExtension(file.getOriginalFilename());
|
||||||
String imageKey = s3UploadService.uploadImageFile(file, extension, projectId);
|
String imageKey = s3UploadService.uploadImageFile(file, extension, projectId);
|
||||||
@ -51,10 +52,12 @@ public class ImageAsyncService {
|
|||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED)
|
||||||
public void createImage(MultipartFile file, String imageKey, Folder folder) {
|
public void createImage(MultipartFile file, String imageKey, Folder folder) {
|
||||||
try {
|
try {
|
||||||
String name = file.getOriginalFilename();
|
String name = file.getOriginalFilename();
|
||||||
String extension = getExtension(name);
|
String extension = getExtension(name);
|
||||||
|
log.debug("image 파일 {} {} {} {}", name, extension, imageKey, folder.getId());
|
||||||
Image image = Image.of(name, imageKey, extension, folder);
|
Image image = Image.of(name, imageKey, extension, folder);
|
||||||
imageRepository.save(image);
|
imageRepository.save(image);
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
|
@ -20,6 +20,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||||
import org.apache.commons.compress.utils.IOUtils;
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@ -55,6 +56,9 @@ public class ImageService {
|
|||||||
@CheckPrivilege(value = PrivilegeType.EDITOR)
|
@CheckPrivilege(value = PrivilegeType.EDITOR)
|
||||||
public void uploadImageList(final List<MultipartFile> imageList, final Integer folderId, final Integer projectId) {
|
public void uploadImageList(final List<MultipartFile> imageList, final Integer folderId, final Integer projectId) {
|
||||||
Folder folder = getOrCreateFolder(folderId, projectId);
|
Folder folder = getOrCreateFolder(folderId, projectId);
|
||||||
|
folderRepository.flush();
|
||||||
|
|
||||||
|
log.debug("folder Id {}, Project Id {}",folder.getId(), folder.getProject().getId());
|
||||||
long prev = System.currentTimeMillis();
|
long prev = System.currentTimeMillis();
|
||||||
|
|
||||||
// 동적 배치 크기 계산
|
// 동적 배치 크기 계산
|
||||||
@ -92,9 +96,6 @@ public class ImageService {
|
|||||||
public void uploadFolderWithImages(final MultipartFile zipFile, final Integer projectId, final Integer folderId) throws IOException {
|
public void uploadFolderWithImages(final MultipartFile zipFile, final Integer projectId, final Integer folderId) throws IOException {
|
||||||
log.debug("파일 크기: {}, 기존 파일 이름: {} ", zipFile.getSize(), zipFile.getOriginalFilename());
|
log.debug("파일 크기: {}, 기존 파일 이름: {} ", zipFile.getSize(), zipFile.getOriginalFilename());
|
||||||
|
|
||||||
Project project = getProject(projectId); // 현재 프로젝트
|
|
||||||
Folder rootFolder = folderRepository.findById(folderId).orElse(null); // 부모 프로젝트
|
|
||||||
|
|
||||||
Path tmpDir = null;
|
Path tmpDir = null;
|
||||||
try {
|
try {
|
||||||
String originalFilename = zipFile.getOriginalFilename();
|
String originalFilename = zipFile.getOriginalFilename();
|
||||||
@ -106,6 +107,9 @@ public class ImageService {
|
|||||||
String zipFolderName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
|
String zipFolderName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
|
||||||
tmpDir = Files.createTempDirectory(zipFolderName);
|
tmpDir = Files.createTempDirectory(zipFolderName);
|
||||||
|
|
||||||
|
Project project = getProject(projectId);
|
||||||
|
Folder rootFolder = getOrCreateFolder(folderId, projectId);
|
||||||
|
|
||||||
unzip(zipFile, tmpDir.toString());
|
unzip(zipFile, tmpDir.toString());
|
||||||
processFolderRecursively(tmpDir.toFile(), rootFolder, project);
|
processFolderRecursively(tmpDir.toFile(), rootFolder, project);
|
||||||
} finally {
|
} finally {
|
||||||
@ -151,6 +155,7 @@ public class ImageService {
|
|||||||
Folder currentFolder = createFolderAndSave(file.getName(), parentFolder, project);
|
Folder currentFolder = createFolderAndSave(file.getName(), parentFolder, project);
|
||||||
processFolderRecursively(file, currentFolder, project);
|
processFolderRecursively(file, currentFolder, project);
|
||||||
} else if (isImageFile(file)) {
|
} else if (isImageFile(file)) {
|
||||||
|
log.debug("파일 {}", file.getName());
|
||||||
uploadAndSave(file, parentFolder, project);
|
uploadAndSave(file, parentFolder, project);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,6 +300,7 @@ public class ImageService {
|
|||||||
* 폴더 생성 또는 가져오기
|
* 폴더 생성 또는 가져오기
|
||||||
* 폴더 생성 작업이 있음으로 트랜잭션 보호
|
* 폴더 생성 작업이 있음으로 트랜잭션 보호
|
||||||
*/
|
*/
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
public Folder getOrCreateFolder(Integer folderId, Integer projectId) {
|
public Folder getOrCreateFolder(Integer folderId, Integer projectId) {
|
||||||
if (folderId != 0) {
|
if (folderId != 0) {
|
||||||
return getFolder(folderId);
|
return getFolder(folderId);
|
||||||
@ -333,11 +339,13 @@ public class ImageService {
|
|||||||
/**
|
/**
|
||||||
* File 업로드 및 저장
|
* File 업로드 및 저장
|
||||||
*/
|
*/
|
||||||
private void uploadAndSave(File file, Folder folder, Project project) {
|
public void uploadAndSave(File file, Folder folder, Project project) {
|
||||||
try {
|
try {
|
||||||
String key = uploadToS3(file, project.getId());
|
String key = uploadToS3(file, project.getId());
|
||||||
|
log.debug("업로드 {}", key);
|
||||||
saveImage(file, key, folder);
|
saveImage(file, key, folder);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
log.error("", e);
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE, "이미지 업로드 중 오류 발생");
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE, "이미지 업로드 중 오류 발생");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,9 +369,11 @@ public class ImageService {
|
|||||||
*/
|
*/
|
||||||
public void saveImage(final File file, final String key, final Folder folder) {
|
public void saveImage(final File file, final String key, final Folder folder) {
|
||||||
try {
|
try {
|
||||||
|
log.debug("파일 생성 완료 : {} {}", file.getName(), key);
|
||||||
Image image = createImage(file.getName(), key, folder);
|
Image image = createImage(file.getName(), key, folder);
|
||||||
imageRepository.save(image);
|
imageRepository.save(image);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
log.error("error ", e);
|
||||||
s3UploadService.deleteImageFromS3(key);
|
s3UploadService.deleteImageFromS3(key);
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE, "에러 발생");
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE, "에러 발생");
|
||||||
}
|
}
|
||||||
@ -374,8 +384,7 @@ public class ImageService {
|
|||||||
*/
|
*/
|
||||||
public String uploadToS3(final MultipartFile file, final Integer projectId) {
|
public String uploadToS3(final MultipartFile file, final Integer projectId) {
|
||||||
String extension = getExtension(file.getOriginalFilename());
|
String extension = getExtension(file.getOriginalFilename());
|
||||||
// return s3UploadService.uploadImageFile(file, extension, projectId);
|
return s3UploadService.uploadImageFile(file, extension, projectId);
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -383,6 +392,7 @@ public class ImageService {
|
|||||||
*/
|
*/
|
||||||
private String uploadToS3(final File file, final Integer projectId) {
|
private String uploadToS3(final File file, final Integer projectId) {
|
||||||
String extension = getExtension(file.getName());
|
String extension = getExtension(file.getName());
|
||||||
|
log.debug("S3에서 업로드 현황 {}, {}, {}", file.getName(), extension, file.getTotalSpace());
|
||||||
return s3UploadService.uploadImageFile(file, extension, projectId);
|
return s3UploadService.uploadImageFile(file, extension, projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ public class S3UploadService {
|
|||||||
*/
|
*/
|
||||||
public String uploadImageFile(final File file, final String extension, final Integer projectId) {
|
public String uploadImageFile(final File file, final String extension, final Integer projectId) {
|
||||||
try (InputStream inputStream = new FileInputStream(file)) {
|
try (InputStream inputStream = new FileInputStream(file)) {
|
||||||
// return uploadImageToS3(inputStream, extension, projectId);
|
return uploadImageToS3(inputStream, extension, projectId);
|
||||||
return "";
|
// return "";
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.debug("이미지 업로드에서 에러 발생 ", e);
|
log.debug("이미지 업로드에서 에러 발생 ", e);
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||||
|
Loading…
Reference in New Issue
Block a user