Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 이슈 카운트 쿼리 수정, 이미지 리사이징 추가 #180

Merged
merged 2 commits into from
Aug 21, 2023
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
4 changes: 4 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ dependencies {
implementation 'com.amazonaws:aws-java-sdk-s3:1.12.518'
testImplementation 'com.amazonaws:aws-java-sdk-s3:1.12.518'

// image
implementation 'net.coobird:thumbnailator:0.4.19'
testImplementation 'net.coobird:thumbnailator:0.4.19'

// mock web server
testImplementation 'com.squareup.okhttp3:okhttp:4.0.1'
testImplementation 'com.squareup.okhttp3:mockwebserver:4.0.1'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package kr.codesquad.issuetracker.application;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;

import javax.imageio.ImageIO;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import net.coobird.thumbnailator.Thumbnails;

import kr.codesquad.issuetracker.application.s3.S3Uploader;
import kr.codesquad.issuetracker.domain.ImageFile;
import kr.codesquad.issuetracker.exception.ApplicationException;
import kr.codesquad.issuetracker.exception.ErrorCode;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
Expand All @@ -20,6 +32,23 @@ public class S3Service {
public String uploadImage(MultipartFile file) {
ImageFile imageFile = ImageFile.from(file);

BufferedImage bufferedImage;
BufferedImage resizedImage;
try {
bufferedImage = ImageIO.read(file.getInputStream());
if (Math.max(bufferedImage.getWidth(), bufferedImage.getHeight()) > 800) {
resizedImage = Thumbnails.of(bufferedImage)
.size(800, 800).asBufferedImage();
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(resizedImage, Objects.requireNonNull(file.getContentType()).split("/")[1], output);
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
imageFile = new ImageFile(file.getOriginalFilename(), file.getContentType(), input,
(long)output.toByteArray().length);
}
} catch (IOException e) {
throw new ApplicationException(ErrorCode.NON_IMAGE_FILE);
}

// 버킷에 저장할 파일 이름 생성
String fileName = UPLOADED_IMAGES_DIR + imageFile.getRandomName();
return s3Uploader.uploadImageToS3(imageFile, fileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public enum ErrorCode {
// File
EMPTY_FILE(400, "파일이 없습니다."),
FILE_INVALID(400, "파일이 유효하지 않습니다."),
NON_IMAGE_FILE(400, "이미지 파일이 아닙니다."),
INVALID_FILE_EXTENSION(400, "지원하지 않는 파일 확장자입니다."),
FILE_IO_EXCEPTION(500, "파일 입출력에 실패했습니다."),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ public class IssueCountMapper {

private int totalCounts;
private int openCounts;
private int closedCounts;

public int getClosedCounts() {
return totalCounts - openCounts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
@RestController
public class FileController {

private final S3Service s3Service;
private final S3Service s3Service;

// 이미지 업로드
@PostMapping("/images/upload")
public ResponseEntity<Map<String, String>> uploadImage(@RequestPart MultipartFile image) {
return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("fileUrl", s3Service.uploadImage(image)));
}
@PostMapping("/images/upload")
public ResponseEntity<Map<String, String>> uploadImage(@RequestPart MultipartFile image) {
return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("fileUrl", s3Service.uploadImage(image)));
}
}
19 changes: 12 additions & 7 deletions backend/src/main/resources/mapper/IssueMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<resultMap id="countResultMap" type="issueCountMapper">
<result property="totalCounts" column="total_counts"/>
<result property="openCounts" column="open_counts"/>
<result property="closedCounts" column="closed_counts"/>
</resultMap>

<select id="findAll" resultMap="issueResultMap">
Expand Down Expand Up @@ -106,11 +107,18 @@
</select>

<select id="countAll" resultMap="countResultMap">
SELECT DISTINCT
COUNT(DISTINCT issue.id) as total_counts,
COUNT(DISTINCT CASE WHEN issue.is_open = TRUE THEN issue.id ELSE NULL END) as open_counts
SELECT
COUNT(DISTINCT
CASE
WHEN #{issueSearch.isOpen} IS NULL THEN issue.id
WHEN #{issueSearch.isOpen} = TRUE AND issue.is_open = TRUE THEN issue.id
WHEN #{issueSearch.isOpen} = FALSE AND issue.is_open = FALSE THEN issue.id
ELSE NULL
END
) as total_counts,
COUNT(DISTINCT CASE WHEN issue.is_open = TRUE THEN issue.id ELSE NULL END) as open_counts,
COUNT(DISTINCT CASE WHEN issue.is_open = FALSE THEN issue.id ELSE NULL END) as closed_counts
FROM issue

LEFT JOIN issue_label ON issue.id = issue_label.issue_id
LEFT JOIN label ON label.id = issue_label.label_id AND label.is_deleted = false
LEFT JOIN issue_assignee ON issue.id = issue_assignee.issue_id
Expand All @@ -122,9 +130,6 @@
</if>

WHERE issue.is_deleted = FALSE
<if test="issueSearch.isOpen != null">
AND issue.is_open = #{issueSearch.isOpen}
</if>
<if test="issueSearch.milestoneName != null">
AND milestone.name = #{issueSearch.milestoneName}
</if>
Expand Down