Skip to content

Commit

Permalink
feat: 파일 다운로드 & 상세 조회 기능 추가 (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
hw130 committed Jan 28, 2024
1 parent 7e27c30 commit 20b2285
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.example.developjeans.controller;
import com.example.developjeans.exception.BusinessLogicException;
import com.example.developjeans.exception.ExceptionCode;
import com.example.developjeans.global.config.aws.S3Service;
import com.example.developjeans.service.PhotoService;
import com.fasterxml.jackson.databind.ser.Serializers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.UrlResource;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand All @@ -16,6 +20,8 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;


@RestController
@RequestMapping("/api/v1/photo")
Expand Down Expand Up @@ -85,6 +91,20 @@ public ResponseEntity<?> getChartLikes(@RequestParam String sort,
}



@Operation(summary = "사진 상세 조회")
@GetMapping("/detail")
public ResponseEntity<?> getPhotoDetail(@RequestParam Long photoId){
return ResponseEntity.ok(photoService.getDetail(photoId));
}

@Operation(summary = "사진 다운로드")
@GetMapping("/download")
public ResponseEntity<?> downloadImage(@RequestParam Long photoId) throws IOException {
return ResponseEntity.ok(photoService.downloadImage(photoId));
}


// @Operation(summary = "사진 차트", description = "모든 사진을 모아볼 수 있는 기능입니다.")
// @GetMapping("/chart")
// public ResponseEntity<Page<GetChartRes>> getChartLikes(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package com.example.developjeans.global.config.aws;

import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v1/categories")
@RequestMapping("/api/v1")
@RequiredArgsConstructor
public class S3Controller {

private final S3Service s3Service;

// @GetMapping()
// public BaseResponse<?> getFileList(@RequestParam String categoryName){
// return new BaseResponse<>(s3Service.getImageList(categoryName));
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.util.IOUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -17,10 +22,13 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static org.springframework.web.servlet.function.RequestPredicates.contentType;

@Slf4j
@Service
@Transactional
Expand Down Expand Up @@ -104,6 +112,39 @@ public String getFile(String fileName) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "파일이 없습니다");
}
}

public ResponseEntity<byte[]> download(String fileUrl) throws IOException { // 객체 다운 fileUrl : 폴더명/파일네임.파일확장자

S3Object s3Object = amazonS3.getObject(new GetObjectRequest(bucket, fileUrl));
S3ObjectInputStream objectInputStream = s3Object.getObjectContent();
byte[] bytes = IOUtils.toByteArray(objectInputStream);

HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(contentType(fileUrl));
httpHeaders.setContentLength(bytes.length);

String[] arr = fileUrl.split("/");
String type = arr[arr.length - 1];
String fileName = URLEncoder.encode(type, "UTF-8").replaceAll("\\+", "%20");
httpHeaders.setContentDispositionFormData("attachment", fileName); // 파일이름 지정

return new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
}

private MediaType contentType(String keyname) {
String[] arr = keyname.split("\\.");
String type = arr[arr.length - 1];
switch (type) {
case "txt":
return MediaType.TEXT_PLAIN;
case "png":
return MediaType.IMAGE_PNG;
case "jpg":
return MediaType.IMAGE_JPEG;
default:
return MediaType.APPLICATION_OCTET_STREAM;
}
}
}
/*
@Service
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe
.requestMatchers(new MvcRequestMatcher(introspector, "/swagger-ui/**")).permitAll()
.requestMatchers(new MvcRequestMatcher(introspector, "/v3/api-docs/**")).permitAll()
.requestMatchers(new MvcRequestMatcher(introspector, "/api/v1/photo/chart")).permitAll()
.requestMatchers(new MvcRequestMatcher(introspector, "/api/v1/categories/**")).permitAll()
.requestMatchers(new MvcRequestMatcher(introspector, "/api/v1/photo/detail")).permitAll()
.requestMatchers(new MvcRequestMatcher(introspector, "/api/v1/photo/download")).permitAll()
// 나머지는 시큐리티 적용
.anyRequest().authenticated()

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/example/developjeans/service/PhotoService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@
import com.example.developjeans.entity.res.GetChartResponse;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.*;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -245,6 +250,20 @@ public GetChartResponse getChart(String sort, int size, Long lastPageId) {
return GetChartResponse.of(photoCursor, totalElements);
}

public PhotoDto.PhotoResponseDto getDetail(Long photoId){

Photo photo = photoRepository.findById(photoId)
.orElseThrow(() -> new EntityNotFoundException("존재하지 않은 사진 ID: " + photoId));

return photoMapper.toResponseDto(photo);

}

public ResponseEntity<byte[]> downloadImage(Long photoId) throws IOException {
Photo photo = photoRepository.findById(photoId)
.orElseThrow(() -> new EntityNotFoundException("존재하지 않은 사진 ID: " + photoId));
return s3Service.download(photo.getImgUrl());
}
// @Transactional(readOnly = true)
// public List<PhotoDto.PhotoChartDto> getChart(String standard, int size){
//
Expand Down

0 comments on commit 20b2285

Please sign in to comment.