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
Expand Up @@ -35,8 +35,9 @@ public ResponseEntity<ResponseBody<ImageSavedSuccessResponse>> uploadProfileImag
Long userId,
@RequestParam MultipartFile image
){
MultipartFile[] images = {image};
return ResponseEntity.ok(createSuccessResponse(
imageService.uploadImage(image, "profile/" + userId + "/")
imageService.uploadImage(images, "profile/" + userId + "/").get(0)
));
}

Expand All @@ -49,8 +50,9 @@ public ResponseEntity<ResponseBody<ImageSavedSuccessResponse>> uploadChatMessage
@RequestParam Long roomId,
@RequestParam MultipartFile image
){
MultipartFile[] images = {image};
return ResponseEntity.ok(createSuccessResponse(
imageService.uploadImage(image, "chat/" + roomId + "/")
imageService.uploadImage(images, "chat/" + roomId + "/").get(0)
));
}

Expand All @@ -62,15 +64,9 @@ public ResponseEntity<ResponseBody<ImageSavedSuccessResponse>> uploadChatMessage
public ResponseEntity<ResponseBody<List<ImageSavedSuccessResponse>>> uploadProductImage(
@RequestParam List<MultipartFile> images
){

List<ImageSavedSuccessResponse> response = new ArrayList<>();
for(int i = 0; i < images.size(); i++){
response.add(
imageService.uploadImage(images.get(i), "product/" + (i + 1) + "/")
);
}

return ResponseEntity.ok(createSuccessResponse(response));
MultipartFile[] imageArray = new MultipartFile[images.size()];
images.toArray(imageArray);
return ResponseEntity.ok(createSuccessResponse(imageService.uploadImage(imageArray, "product/" + 1 + "/")));
}

@PostMapping("/image/review")
Expand All @@ -80,8 +76,9 @@ public ResponseEntity<ResponseBody<ImageSavedSuccessResponse>> uploadReviewImage
Long userId,
@RequestParam MultipartFile image
){
MultipartFile[] images = {image};
return ResponseEntity.ok(createSuccessResponse(
imageService.uploadImage(image, "review/" + userId + "/")
imageService.uploadImage(images, "review/" + userId + "/").get(0)
));
}
/**
Expand Down
81 changes: 59 additions & 22 deletions src/main/java/com/uhdyl/backend/image/service/ImageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,22 @@
import com.uhdyl.backend.image.dto.response.ImagePublicIdResponse;
import com.uhdyl.backend.image.dto.response.ImageSavedSuccessResponse;
import com.uhdyl.backend.image.repository.ImageRepository;
import com.uhdyl.backend.product.domain.Product;
import com.uhdyl.backend.product.repository.ProductRepository;
import com.uhdyl.backend.review.domain.Review;
import com.uhdyl.backend.review.repository.ReviewRepository;
import com.uhdyl.backend.user.domain.User;
import com.uhdyl.backend.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ImageService {
Expand All @@ -40,30 +39,53 @@ public class ImageService {
private final ReviewRepository reviewRepository;
private final ProductRepository productRepository;

public ImageSavedSuccessResponse uploadImage(MultipartFile image, String folderPath){
private static final Set<String> ALLOWED_CONTENT_TYPES =
Set.of("image/jpeg", "image/png", "image/webp", "image/gif");

if(image == null || image.isEmpty())
throw new BusinessException(ExceptionType.INVALID_IMAGE_FILE);
public List<ImageSavedSuccessResponse> uploadImage(MultipartFile[] images, String folderPath){

if(image.getSize() > 1024 * 1024 * 5)
throw new BusinessException(ExceptionType.IMAGE_SIZE_EXCEEDED);
List<String> uploadedImagesPublicId = new ArrayList<>();
List<ImageSavedSuccessResponse> responses = new ArrayList<>();

try {
Map<?, ?> result = cloudinary.uploader().upload(
image.getBytes(),
Map.of(
"folder", folderPath,
"public_id", UUID.randomUUID().toString()
)
);

if(result.get("secure_url") == null || result.get("public_id") == null)
throw new BusinessException(ExceptionType.IMAGE_UPLOAD_FAILED);

return ImageSavedSuccessResponse.to(result.get("secure_url").toString(), result.get("public_id").toString());
} catch (IOException e) {
for (MultipartFile image : images) {

if (image == null || image.isEmpty())
throw new BusinessException(ExceptionType.INVALID_IMAGE_FILE);

if (image.getSize() > 1024 * 1024 * 5)
throw new BusinessException(ExceptionType.IMAGE_SIZE_EXCEEDED);

String contentType = image.getContentType();
if (!ALLOWED_CONTENT_TYPES.contains(contentType))
throw new BusinessException(ExceptionType.INVALID_IMAGE_FILE);

Map<?, ?> result = cloudinary.uploader().upload(
image.getBytes(),
Map.of(
"folder", folderPath,
"public_id", UUID.randomUUID().toString()
)
);


if (result.get("secure_url") == null || result.get("public_id") == null)
throw new BusinessException(ExceptionType.IMAGE_UPLOAD_FAILED);

uploadedImagesPublicId.add(result.get("public_id").toString());
responses.add(ImageSavedSuccessResponse.to(result.get("secure_url").toString(), result.get("public_id").toString()));

}
}
catch (BusinessException e) {
rollbackImage(uploadedImagesPublicId);
throw e;
}
catch (Exception e) {
rollbackImage(uploadedImagesPublicId);
throw new BusinessException(ExceptionType.IMAGE_UPLOAD_FAILED);
}
return responses;
}

@Transactional
Expand Down Expand Up @@ -147,4 +169,19 @@ public ImagePublicIdResponse getPublicId(Long userId, String imageUrl, ImageType
}
return ImagePublicIdResponse.to("이미지가 존재하지 않습니다.");
}

public void rollbackImage(List<String> publicIds){
try{
for (String publicId : publicIds) {
try {
cloudinary.uploader().destroy(publicId, ObjectUtils.emptyMap());
} catch (IOException e) {
log.warn("이미지 롤백에 실패했습니다. publicId : {}", publicId);
}
}
}
catch (Exception e){
log.warn("이미지 롤백이 일부 실패했습니다.");
}
}
}