Skip to content

Commit

Permalink
✨ feat: Webp 압축 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
kimday0326 committed Apr 15, 2024
1 parent e05bad9 commit 6f1fc39
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import com.sponus.coreinfraredis.entity.AnnouncementView;
import com.sponus.coreinfraredis.repository.AnnouncementViewRepository;
import com.sponus.coreinfraredis.util.RedisUtil;
import com.sponus.coreinfras3.S3Util;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.announcement.dto.request.AnnouncementCreateRequest;
import com.sponus.sponusbe.domain.announcement.dto.request.AnnouncementUpdateRequest;
import com.sponus.sponusbe.domain.announcement.dto.response.AnnouncementCreateResponse;
Expand All @@ -39,7 +39,7 @@ public class AnnouncementService {
private final AnnouncementRepository announcementRepository;
private final AnnouncementViewRepository announcementViewRepository;
private final ProposeRepository proposeRepository;
private final S3Util s3Util;
private final S3Service s3Service;
private final RedisUtil redisUtil;

public AnnouncementCreateResponse createAnnouncement(
Expand Down Expand Up @@ -159,11 +159,11 @@ private boolean isOrganizationsAnnouncement(Long organizationId, Announcement an
private void updateAnnouncementImages(Announcement announcement, List<MultipartFile> images) {
// 공고의 이미지는 반드시 존재해야함
announcement.getAnnouncementImages().stream().forEach(image -> {
s3Util.deleteFile(image.getUrl());
s3Service.deleteFile(image.getUrl());
});
announcement.getAnnouncementImages().clear();
images.forEach(image -> {
final String url = s3Util.uploadFile(image);
final String url = s3Service.uploadFile(image);
AnnouncementImage announcementImage = AnnouncementImage.builder()
.name(image.getOriginalFilename())
.url(url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import com.sponus.coredomain.domain.organization.Organization;
import com.sponus.coredomain.domain.organization.repository.OrganizationRepository;
import com.sponus.coreinfraemail.EmailUtil;
import com.sponus.coreinfras3.S3Util;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.notification.exception.NotificationErrorCode;
import com.sponus.sponusbe.domain.notification.exception.NotificationException;
import com.sponus.sponusbe.domain.organization.dto.OrganizationJoinRequest;
Expand All @@ -35,7 +35,7 @@ public class OrganizationService {
private final OrganizationRepository organizationRepository;
private final NotificationRepository notificationRepository;
private final PasswordEncoder passwordEncoder;
private final S3Util s3Util;
private final S3Service s3Service;
private final EmailUtil emailUtil;

public OrganizationJoinResponse join(OrganizationJoinRequest request) {
Expand All @@ -56,8 +56,8 @@ public void updateOrganization(Long organizationId, OrganizationUpdateRequest re
request.managerContactPreference()
);
if (attachment != null) {
s3Util.deleteFile(organization.getImageUrl());
String newUrl = s3Util.uploadFile(attachment);
s3Service.deleteFile(organization.getImageUrl());
String newUrl = s3Service.uploadFile(attachment);
organization.updateImageUrl(newUrl);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import com.sponus.coredomain.domain.propose.ProposeStatus;
import com.sponus.coredomain.domain.propose.repository.ProposeRepository;
import com.sponus.coreinfrafirebase.FirebaseService;
import com.sponus.coreinfras3.S3Util;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementErrorCode;
import com.sponus.sponusbe.domain.announcement.exception.AnnouncementException;
import com.sponus.sponusbe.domain.propose.dto.request.ProposeCreateRequest;
Expand All @@ -35,10 +35,10 @@
@Service
public class ProposeService {

private final S3Util s3Util;
private final FirebaseService firebaseService;
private final ProposeRepository proposeRepository;
private final AnnouncementRepository announcementRepository;
private final S3Service s3Service;
private final FirebaseService firebaseService;

public ProposeCreateResponse createPropose(
Organization authOrganization,
Expand All @@ -57,7 +57,7 @@ public ProposeCreateResponse createPropose(

// 제안의 첨부파일 업로드
attachments.forEach(file -> {
final String url = s3Util.uploadFile(file);
final String url = s3Service.uploadFile(file);
ProposeAttachment proposeAttachment = ProposeAttachment.builder()
.name(file.getOriginalFilename())
.url(url)
Expand Down Expand Up @@ -149,7 +149,7 @@ private boolean isProposedOrganization(Long organizationId, Propose propose) {
private void updateProposeAttachments(Propose propose, List<MultipartFile> attachments) {
propose.getProposeAttachments().clear();
attachments.forEach(attachment -> {
final String url = s3Util.uploadFile(attachment);
final String url = s3Service.uploadFile(attachment);
ProposeAttachment proposeAttachment = ProposeAttachment.builder()
.name(attachment.getOriginalFilename())
.url(url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import com.sponus.coredomain.domain.report.ReportImage;
import com.sponus.coredomain.domain.report.repository.ReportRepository;
import com.sponus.coreinfrafirebase.FirebaseService;
import com.sponus.coreinfras3.S3Util;
import com.sponus.coreinfras3.S3Service;
import com.sponus.sponusbe.domain.propose.exception.ProposeErrorCode;
import com.sponus.sponusbe.domain.report.dto.request.ReportCreateRequest;
import com.sponus.sponusbe.domain.report.dto.request.ReportUpdateRequest;
Expand All @@ -35,7 +35,7 @@ public class ReportService {

private final ReportRepository reportRepository;
private final ProposeRepository proposeRepository;
private final S3Util s3Util;
private final S3Service s3Service;
private final FirebaseService firebaseService;

public ReportCreateResponse createReport(
Expand Down Expand Up @@ -86,7 +86,7 @@ private boolean isOrganizationsReport(Long organizationId, Report report) {
private void setReportImages(List<MultipartFile> images, Report report) {
report.getReportImages().clear();
images.forEach(image -> {
final String url = s3Util.uploadFile(image);
final String url = s3Service.uploadFile(image);
ReportImage reportImage = ReportImage.builder()
.name(image.getOriginalFilename())
.url(url)
Expand All @@ -98,7 +98,7 @@ private void setReportImages(List<MultipartFile> images, Report report) {
private void setReportAttachments(List<MultipartFile> attachments, Report report) {
report.getReportAttachments().clear();
attachments.forEach(attachment -> {
final String url = s3Util.uploadFile(attachment);
final String url = s3Service.uploadFile(attachment);
ReportAttachment reportAttachment = ReportAttachment.builder()
.name(attachment.getOriginalFilename())
.url(url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.web.multipart.MultipartFile;

import com.sponus.coredomain.domain.common.ApiResponse;
import com.sponus.coreinfras3.S3Util;
import com.sponus.coreinfras3.S3Service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -22,23 +22,28 @@
@RequestMapping("/api/v1/s3")
public class S3TestController {

private final S3Util s3Util;
private final S3Service s3Service;

@PostMapping(value = "/uploadFile", consumes = "multipart/form-data")
public ApiResponse<String> uploadFile(@RequestPart(value = "file", required = false) MultipartFile file) {
return ApiResponse.onSuccess(s3Service.uploadFile(file));
}

@PostMapping(value = "/uploadImage", consumes = "multipart/form-data")
public ApiResponse<String> uploadImage(@RequestPart(value = "file", required = false) MultipartFile file) {
return ApiResponse.onSuccess(s3Util.uploadFile(file));
return ApiResponse.onSuccess(s3Service.uploadImage(file));
}

@DeleteMapping(value = "/deleteImage")
public ApiResponse<String> deleteImage(@RequestBody String path) {
String image = path.substring(path.lastIndexOf('/') + 1);
return ApiResponse.onSuccess(s3Util.deleteFile(image));
return ApiResponse.onSuccess(s3Service.deleteFile(image));
}

@PostMapping(value = "/uploadImages", consumes = "multipart/form-data")
public ApiResponse<List<String>> uploadImages(
@RequestPart(value = "files", required = false) List<MultipartFile> files) {
return ApiResponse.onSuccess(s3Util.uploadFiles(files));
return ApiResponse.onSuccess(s3Service.uploadFiles(files));
}

}
2 changes: 2 additions & 0 deletions core/core-infra-s3/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation 'com.sksamuel.scrimage:scrimage-core:4.1.1'
implementation 'com.sksamuel.scrimage:scrimage-webp:4.1.1'
}

bootJar { enabled = false }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.sponus.coreinfras3;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;

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

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.sponus.coreinfras3.convert.webp.WebpConvertService;
import com.sponus.coreinfras3.util.FileUtils;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class S3Service {

private final AmazonS3 amazonS3;

private final S3Config s3Config;

private final WebpConvertService webpConvertService;

public String uploadImage(MultipartFile multipartFile) {
File file = FileUtils.convertToFile(multipartFile);
return uploadImage(file);
}

public String uploadImage(File file) {
File webpFile = webpConvertService.convertToWebP(file);
return uploadFile(webpFile);
}

public String uploadFile(MultipartFile multipartFile) {
File file = FileUtils.convertToFile(multipartFile);
return uploadFile(file);
}

public String uploadFile(File file) {
String fileName = getFileNamePrefix() + file.getName();

amazonS3.putObject(new PutObjectRequest(s3Config.getBucket(), s3Config.getFolder() + fileName, file));
try {
Files.delete(file.toPath());
} catch (IOException e) {
throw new IllegalArgumentException("Failed to delete file", e);
}

return amazonS3.getUrl(s3Config.getBucket(), s3Config.getFolder() + fileName).toString();
}

public String deleteFile(String image) {
try {
amazonS3.deleteObject(s3Config.getBucket(), s3Config.getFolder() + image);
} catch (Exception e) {
log.error("error at AmazonS3Manager deleteFile : {}", (Object)e.getStackTrace());
}
return "삭제 성공";
}

public List<String> uploadFiles(List<MultipartFile> files) {
return files.stream()
.map(this::uploadFile)
.toList();
}

private String getFileNamePrefix() {
return UUID.randomUUID().toString().substring(0, 5) + "-";
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.sponus.coreinfras3.convert;

public enum ImageFormat {
JPEG, JPG, PNG, GIF, WEBP;

public static ImageFormat of(String format) {
try {
return ImageFormat.valueOf(format.toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Unsupported image format: " + format);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.sponus.coreinfras3.convert.webp;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import org.springframework.stereotype.Service;

import com.sksamuel.scrimage.ImmutableImage;
import com.sksamuel.scrimage.webp.WebpWriter;
import com.sponus.coreinfras3.convert.ImageFormat;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class Jpg2WebpStrategy implements WebpConvertStrategy {

@Override
public boolean identify(ImageFormat imageFormat) {
return imageFormat == ImageFormat.JPG || imageFormat == ImageFormat.JPEG;
}

@Override
public File convert(String fileName, File file, WebpCompressionParam param) {
try {
File webpFile = ImmutableImage.loader()
.fromFile(file)
.output(WebpWriter.DEFAULT, new File(fileName + ".webp"));
Files.delete(file.toPath());
return webpFile;
} catch (IOException e) {
log.error("JPG -> WebP conversion failed, cancelling conversion. {}", e.getMessage());
return file;
}
}
}
Loading

0 comments on commit 6f1fc39

Please sign in to comment.