티스토리 뷰
일단 AWS의 스토리지 서비스인 S3를 쓰지 않고 이미지를 서버에 저장해보자!
❕Spring Web이 파일 업로드 기능을 제공!
✔️ 이미지를 저장하기 위해선 프론트에서 요청 바디의 형식을 multipart/form-data로 보내야 함!
(일반적인 요청 방식인 application/x-www-form-urlencoded는 바디 내용을 문자로 보내는데, 파일은 문자가 아니라 바이너리 데이터이기 때문!)
❔ multipart/form-data
: 다른 종류의 여러 파일과 폼의 내용을 함께 전송O
: 각 항목별(Part)로 헤더가 추가
📌 코드 스니펫
1️⃣ application.properties에 실제 파일이 저장되는 경로 지정 ← 실제로 디렉토리 만들어 놓기!
file.dir=/Users/uijin/Spring/file/
❕ (참고) application.properties와 application.yml 변환해주는 사이트
https://mageddo.com/tools/yaml-converter
2️⃣ 이미지가 필요한 도메인에 파일을 멤버변수 넣어주기!
@Data
public class Item {
private Long id;
private String itemName;
private UploadFile attachFile;
private List<UploadFile> imageFiles;
}
2️⃣ File 도메인 만들기
@Data
public class UploadFile {
private String uploadfileName;
private String storeFileName; //서버 내부에서 관리하는 파일명
public file(String uploadfileName, String storeFileName) {
this.uploadFileName = uploadfileName;
this.storeFileName = storeFileName;
}
}
3️⃣ (file > ) FileStore 생성 - 파일 저장과 관련된 업무 처리
@Component
public class FileStore {
@Value("${file.dir}") //application.properties에 저장해 둔 파일 경로
private String fileDir;
public String getFullPath(String filename) {
return fileDir + filename;
}
public List<UploadFile> storeFiles(List<MultipartFile> multipartFiles) throws IOException {
List<UploadFile> storeFileResult = new ArrayList<>();
for (MultipartFile multipartFile : multipartFiles) {
if (!multipartFile.isEmpty()) {
storeFileResult.add(storeFile(multipartFile));
}
}
return storeFileResult;
}
public UploadFile storeFile(MultipartFile multipartFile) throws IOException {
if (multipartFile.isEmpty()) {
return null;
}
String originalFilename = multipartFile.getOriginalFilename();
String storeFileName = createStoreFileName(originalFilename);
multipartFile.transferTo(new File(getFullPath(storeFileName)));
return new UploadFile(originalFilename, storeFileName);
}
private String createStoreFileName(String originalFilename) { //uuid로 서버에 저장될 파일명 생성
String ext = extractExt(originalFilename);
String uuid = UUID.randomUUID().toString();
return uuid + "." + ext;
}
private String extractExt(String originalFilename) { //png와 같은 확장자 추출!
int pos = originalFilename.lastIndexOf(".");
return originalFilename.substring(pos + 1);
}
}
4️⃣ 컨트롤러 작성!
@Slf4j
@Controller
@RequiredArgsConstructor
public class ItemController {
private final ItemRepository itemRepository;
private final FileStore fileStore;
@PostMapping("/items/new")
public SaveItemResponse saveItem(@RequestBody SaveItemRequest request) throws IOException {
UploadFile attachFile = fileStore.storeFile(request.getAttachFile());
List<UploadFile> storeImageFiles = fileStore.storeFiles(request.getImageFiles());
//데이터베이스에 저장
Item item = new Item();
item.setItemName(form.getItemName());
item.setAttachFile(attachFile);
item.setImageFiles(storeImageFiles);
itemRepository.save(item);
return new SaveItemResponse(item);
}
// 이미지 파일 보기
@ResponseBody
@GetMapping("/images/{filename}")
public Resource downloadImage(@PathVariable String filename) throws MalformedURLException {
return new UrlResource("file:" + fileStore.getFullPath(filename));
}
// 첨부파일 다운로드
@GetMapping("/attach/{itemId}")
public ResponseEntity<Resource> downloadAttach(@PathVariable Long itemId) throws MalformedURLException {
Item item = itemRepository.findById(itemId);
String storeFileName = item.getAttachFile().getStoreFileName();
String uploadFileName = item.getAttachFile().getUploadFileName();
UrlResource resource = new UrlResource("file:" + fileStore.getFullPath(storeFileName));
log.info("uploadFileName={}", uploadFileName);
String encodedUploadFileName = UriUtils.encode(uploadFileName, StandardCharsets.UTF_8);
String contentDisposition = "attachment; filename=\"" + encodedUploadFileName + "\"";
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
.body(resource);
}
/**
* DTO
*/
@Data
static class SaveItemRequest {
// ...
private MultipartFile attachFile;
private List<MultipartFile> imageFiles;
}
@Data
static class SaveItemResponse {...}
}
📚 추후 공부해보고 싶은 부분
✔️ AWS S3
'백엔드 > Spring' 카테고리의 다른 글
프로젝트 환경설정 (0) | 2023.07.06 |
---|---|
빌드하기 (0) | 2023.07.04 |
권한 관리 - 스프링 인터셉터 (0) | 2023.06.15 |
로그인 1 - 쿠키와 세션 (1) | 2023.06.14 |
스프링 부트와 JPA 활용1 (0) | 2023.05.17 |