Merge branch 'be/feat/217-image' into 'be/develop'
Feat: 이미지 저장시에 Json 파일도 저장하는 로직 추가 S11P21S002-217 See merge request s11-s-project/S11P21S002!131
This commit is contained in:
commit
a337b8cde2
@ -33,9 +33,9 @@ public class ImageController {
|
|||||||
@SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR})
|
@SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR})
|
||||||
public void uploadImage(
|
public void uploadImage(
|
||||||
@CurrentUser final Integer memberId,
|
@CurrentUser final Integer memberId,
|
||||||
@PathVariable("folder_id") final Integer folderId,
|
|
||||||
@PathVariable("project_id") final Integer projectId,
|
@PathVariable("project_id") final Integer projectId,
|
||||||
@Parameter(name = "폴더에 추가 할 이미지 리스트", description = "MultiPartFile을 imageList로 추가해준다.", example = "") @RequestBody final List<MultipartFile> imageList) {
|
@PathVariable("folder_id") final Integer folderId,
|
||||||
|
@Parameter(name = "폴더에 추가 할 이미지 리스트", description = "MultiPartFile을 imageList로 추가해준다.", example = "") @RequestPart final List<MultipartFile> imageList) {
|
||||||
imageService.uploadImageList(imageList, folderId, projectId, memberId);
|
imageService.uploadImageList(imageList, folderId, projectId, memberId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,8 +45,9 @@ public class ImageController {
|
|||||||
@SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR})
|
@SwaggerApiError({ErrorCode.BAD_REQUEST, ErrorCode.NOT_AUTHOR, ErrorCode.SERVER_ERROR})
|
||||||
public void uploadFolder(
|
public void uploadFolder(
|
||||||
@Parameter(name = "폴더", description = "MultiPartFile을 폴더나 zip으로 추가해준다.", example = "") @RequestPart final MultipartFile folderZip,
|
@Parameter(name = "폴더", description = "MultiPartFile을 폴더나 zip으로 추가해준다.", example = "") @RequestPart final MultipartFile folderZip,
|
||||||
@PathVariable("project_id") Integer projectId) throws IOException {
|
@PathVariable("project_id") final Integer projectId,
|
||||||
imageService.uploadFolderWithImages(folderZip, projectId);
|
@PathVariable("folder_id") final Integer folderId) throws IOException {
|
||||||
|
imageService.uploadFolderWithImages(folderZip, projectId, folderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{image_id}")
|
@GetMapping("/{image_id}")
|
||||||
|
@ -40,12 +40,6 @@ public class Image extends BaseEntity {
|
|||||||
@Column(name = "image_extenstion", nullable = false, length = 10)
|
@Column(name = "image_extenstion", nullable = false, length = 10)
|
||||||
private String extension;
|
private String extension;
|
||||||
|
|
||||||
/**
|
|
||||||
* 이미지 순서
|
|
||||||
*/
|
|
||||||
@Column(name = "image_order", nullable = false)
|
|
||||||
private Integer order;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 이미지 레이블링 상태
|
* 이미지 레이블링 상태
|
||||||
*/
|
*/
|
||||||
@ -61,16 +55,15 @@ public class Image extends BaseEntity {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Folder folder;
|
private Folder folder;
|
||||||
|
|
||||||
private Image(final String imageTitle, final String imageKey, final String extension, final Integer order, final Folder folder) {
|
private Image(final String imageTitle, final String imageKey, final String extension, final Folder folder) {
|
||||||
this.title = imageTitle;
|
this.title = imageTitle;
|
||||||
this.imageKey = imageKey;
|
this.imageKey = imageKey;
|
||||||
this.extension = extension;
|
this.extension = extension;
|
||||||
this.order = order;
|
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Image of(final String imageTitle, final String imageKey,final String extension, final Integer order, final Folder folder) {
|
public static Image of(final String imageTitle, final String imageKey, final String extension, final Folder folder) {
|
||||||
return new Image(imageTitle, imageKey, extension, order, folder);
|
return new Image(imageTitle, imageKey, extension, folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveFolder(final Folder moveFolder) {
|
public void moveFolder(final Folder moveFolder) {
|
||||||
@ -81,11 +74,11 @@ public class Image extends BaseEntity {
|
|||||||
this.status = labelStatus;
|
this.status = labelStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImagePath(){
|
public String getImagePath() {
|
||||||
return this.imageKey + "." + this.extension;
|
return this.imageKey + "." + this.extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDataPath(){
|
public String getDataPath() {
|
||||||
return this.imageKey + ".json";
|
return this.imageKey + ".json";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,19 @@ import java.util.Optional;
|
|||||||
|
|
||||||
public interface ImageRepository extends JpaRepository<Image, Long> {
|
public interface ImageRepository extends JpaRepository<Image, Long> {
|
||||||
|
|
||||||
// todo N + 1 발생할듯
|
|
||||||
@Query("select i from Image i " +
|
@Query("select i from Image i " +
|
||||||
"where i.folder.project.id = :projectId")
|
"join fetch i.folder f " +
|
||||||
|
"join fetch f.project p " +
|
||||||
|
"where p.id = :projectId")
|
||||||
List<Image> findImagesByProjectId(@Param("projectId") Integer projectId);
|
List<Image> findImagesByProjectId(@Param("projectId") Integer projectId);
|
||||||
|
|
||||||
|
|
||||||
Optional<Image> findByIdAndFolderIdAndFolderProjectId(Long imageId, Integer folderId, Integer projectId);
|
Optional<Image> findByIdAndFolderIdAndFolderProjectId(Long imageId, Integer folderId, Integer projectId);
|
||||||
|
|
||||||
@Query("SELECT i FROM Image i " +
|
@Query("SELECT i FROM Image i " +
|
||||||
|
"JOIN FETCH i.folder f " +
|
||||||
|
"JOIN FETCH f.project p " +
|
||||||
"WHERE i.id = :imageId " +
|
"WHERE i.id = :imageId " +
|
||||||
"AND i.folder.project.id = :projectId ")
|
"AND p.id = :projectId")
|
||||||
Optional<Image> findByIdAndProjectId(@Param("imageId") Long imageId, @Param("projectId") Integer projectId);
|
Optional<Image> findByIdAndProjectId(@Param("imageId") Long imageId, @Param("projectId") Integer projectId);
|
||||||
}
|
}
|
||||||
|
@ -40,19 +40,20 @@ public class ImageService {
|
|||||||
private final FolderRepository folderRepository;
|
private final FolderRepository folderRepository;
|
||||||
private final ProjectRepository projectRepository;
|
private final ProjectRepository projectRepository;
|
||||||
|
|
||||||
private static int orderCount = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 이미지 리스트 업로드
|
* 이미지 리스트 업로드
|
||||||
*/
|
*/
|
||||||
@CheckPrivilege(value = PrivilegeType.EDITOR)
|
@CheckPrivilege(value = PrivilegeType.EDITOR)
|
||||||
public void uploadImageList(final List<MultipartFile> imageList, final Integer folderId, final Integer projectId, final Integer memberId) {
|
public void uploadImageList(final List<MultipartFile> imageList, final Integer folderId, final Integer projectId, final Integer memberId) {
|
||||||
Folder folder = getFolder(folderId);
|
Folder folder = null;
|
||||||
for (int order = 0; order < imageList.size(); order++) {
|
if (folderId != 0) {
|
||||||
MultipartFile file = imageList.get(order);
|
folder = getFolder(folderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MultipartFile file : imageList) {
|
||||||
String extension = getExtension(file);
|
String extension = getExtension(file);
|
||||||
String imageKey = s3UploadService.upload(file, extension, projectId);
|
String imageKey = s3UploadService.upload(file, extension, projectId);
|
||||||
Image image = Image.of(file.getOriginalFilename(), imageKey, extension, order, folder);
|
Image image = Image.of(file.getOriginalFilename(), imageKey, extension, folder);
|
||||||
imageRepository.save(image);
|
imageRepository.save(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,15 +117,15 @@ public class ImageService {
|
|||||||
save(imageId, labelRequest.getData());
|
save(imageId, labelRequest.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uploadFolderWithImages(MultipartFile folderOrZip, Integer projectId) throws IOException {
|
public void uploadFolderWithImages(MultipartFile folderOrZip, Integer projectId, Integer folderId) throws IOException {
|
||||||
orderCount = 0;
|
|
||||||
|
|
||||||
// 프로젝트 정보 가져오기
|
// 프로젝트 정보 가져오기
|
||||||
Project project = projectRepository.findById(projectId)
|
Project project = projectRepository.findById(projectId)
|
||||||
.orElseThrow(() -> new CustomException(ErrorCode.PROJECT_NOT_FOUND));
|
.orElseThrow(() -> new CustomException(ErrorCode.PROJECT_NOT_FOUND));
|
||||||
|
|
||||||
// 부모 폴더가 최상위인지 확인
|
|
||||||
Folder parentFolder = null;
|
Folder parentFolder = null;
|
||||||
|
if (folderId != 0) {
|
||||||
|
parentFolder = getFolder(folderId);
|
||||||
|
}
|
||||||
|
|
||||||
// 파일이 zip 파일인지 확인
|
// 파일이 zip 파일인지 확인
|
||||||
String originalFilename = folderOrZip.getOriginalFilename();
|
String originalFilename = folderOrZip.getOriginalFilename();
|
||||||
@ -166,7 +167,7 @@ public class ImageService {
|
|||||||
// InputStream으로 S3 업로드
|
// InputStream으로 S3 업로드
|
||||||
String imageKey = s3UploadService.uploadFromInputStream(inputStream, extension, project.getId(), file.getName());
|
String imageKey = s3UploadService.uploadFromInputStream(inputStream, extension, project.getId(), file.getName());
|
||||||
|
|
||||||
Image image = Image.of(file.getName(), imageKey, extension, orderCount++, currentFolder);
|
Image image = Image.of(file.getName(), imageKey, extension, currentFolder);
|
||||||
imageRepository.save(image);
|
imageRepository.save(image);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||||
|
@ -12,6 +12,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -131,6 +133,12 @@ public class S3UploadService {
|
|||||||
PutObjectRequest putRequest = new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata);
|
PutObjectRequest putRequest = new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata);
|
||||||
|
|
||||||
amazonS3.putObject(putRequest); // S3 파일 업로드
|
amazonS3.putObject(putRequest); // S3 파일 업로드
|
||||||
|
|
||||||
|
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(bytes));
|
||||||
|
int imageWidth = bufferedImage.getWidth();
|
||||||
|
int imageHeight = bufferedImage.getHeight();
|
||||||
|
|
||||||
|
uploadJsonWithDimensions(s3Key, imageWidth, imageHeight);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("", e);
|
log.error("", e);
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||||
@ -174,9 +182,11 @@ public class S3UploadService {
|
|||||||
|
|
||||||
public String uploadFromInputStream(InputStream inputStream, String extension, Integer projectId, String fileName) {
|
public String uploadFromInputStream(InputStream inputStream, String extension, Integer projectId, String fileName) {
|
||||||
try {
|
try {
|
||||||
|
// UUID로 S3 파일 이름 생성
|
||||||
String s3Key = getS3FileName(projectId);
|
String s3Key = getS3FileName(projectId);
|
||||||
String s3FileName = s3Key + "." + extension;
|
String s3FileName = s3Key + "." + extension;
|
||||||
|
|
||||||
|
// 이미지 파일 업로드
|
||||||
byte[] bytes = IOUtils.toByteArray(inputStream);
|
byte[] bytes = IOUtils.toByteArray(inputStream);
|
||||||
|
|
||||||
ObjectMetadata metadata = new ObjectMetadata();
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
@ -185,12 +195,44 @@ public class S3UploadService {
|
|||||||
|
|
||||||
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) {
|
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) {
|
||||||
PutObjectRequest putRequest = new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata);
|
PutObjectRequest putRequest = new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata);
|
||||||
amazonS3.putObject(putRequest);
|
amazonS3.putObject(putRequest); // 이미지 업로드
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 이미지 높이와 너비 추출
|
||||||
|
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(bytes));
|
||||||
|
int imageWidth = bufferedImage.getWidth();
|
||||||
|
int imageHeight = bufferedImage.getHeight();
|
||||||
|
|
||||||
|
// 너비와 높이를 포함한 JSON 업로드
|
||||||
|
uploadJsonWithDimensions(s3Key, imageWidth, imageHeight); // JSON 파일 업로드 메서드 호출
|
||||||
|
|
||||||
return url + "/" + s3Key;
|
return url + "/" + s3Key;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 이미지의 너비와 높이를 포함하는 JSON 파일 업로드
|
||||||
|
private void uploadJsonWithDimensions(String s3Key, int width, int height) {
|
||||||
|
try {
|
||||||
|
// JSON 파일 이름 생성 (s3Key + ".json")
|
||||||
|
String jsonFileName = s3Key + ".json";
|
||||||
|
|
||||||
|
// 이미지의 너비와 높이를 포함한 JSON 데이터 생성
|
||||||
|
String jsonContent = "{\n\"imageHeight\": " + height + ",\n\"imageWidth\": " + width + "\n}";
|
||||||
|
|
||||||
|
byte[] jsonBytes = jsonContent.getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
ObjectMetadata jsonMetadata = new ObjectMetadata();
|
||||||
|
jsonMetadata.setContentType("application/json");
|
||||||
|
jsonMetadata.setContentLength(jsonBytes.length);
|
||||||
|
|
||||||
|
try (ByteArrayInputStream jsonInputStream = new ByteArrayInputStream(jsonBytes)) {
|
||||||
|
PutObjectRequest jsonPutRequest = new PutObjectRequest(bucket, jsonFileName, jsonInputStream, jsonMetadata);
|
||||||
|
amazonS3.putObject(jsonPutRequest); // JSON 파일 업로드
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user