사진 업로드 샘플링 2

coding S's avatar
Apr 19, 2024
사진 업로드 샘플링 2

[ 사진 업로드 하기 ]

notion image
notion image
사진 업로드 버튼을 누르면 터진다. 고치자

[ PicController ]

@Controller public class PicController { @PostMapping("/upload") public String upload() { return "redirect:/"; }
 

[ PicRequest ]

💡
사진 업로드를 하려면 DTO가 필요하다!
package com.mtcoding.fileapp.pic; import lombok.Data; import org.springframework.web.multipart.MultipartFile; public class PicRequest { @Data public static class UploadDTO { private String title; //키값이 타이틀 private MultipartFile imgFile; //키값이 imgFile } }
notion image
"키값이 타이틀", "키값이 imgFile" 이라는 표현은 UploadDTO 클래스의 각 필드명을 가리킨다. 이 필드명들은 데이터를 전달할 때 사용되는 키로, 이 키를 통해 데이터를 가져오거나 설정할 수 있다. 여기에서 title과 imgFile은 UploadDTO 클래스의 키값 혹은 필드명이라고 볼 수 있다. title: 업로드할 사진의 타이틀 정보를 담는다. 예를 들어, 사용자가 업로드하는 사진에 '여행사진'이라는 타이틀을 붙였다면, '여행사진'이라는 값이 title 필드에 저장된다. imgFile: 실제로 업로드 되는 이미지 파일 정보를 담는다. 사용자가 선택한 이미지 파일이 imgFile 필드에 저장된다. 따라서 이 UploadDTO 객체를 통해 업로드하는 사진의 타이틀과 이미지 파일 정보를 한 번에 전달할 수 있다.
 

[ PicController (확인 위해 sout) ]

@Controller public class PicController { @PostMapping("/upload") public String upload(PicRequest.UploadDTO requestDTO) { System.out.println(requestDTO.getTitle()); MultipartFile imgFile = requestDTO.getImgFile(); //객체를 받고 //base24로 변환된 문자열? //컨버터해서 들고있다. 바이트로 받아야하니까 System.out.println(imgFile.getContentType()); //무슨 파일인지 확인해보고 System.out.println(imgFile.getOriginalFilename()); return "redirect:/"; }
notion image
둘 다 문자열로 컨버트 되어야하니까 base24로 보낸다. 사진은 문자열이 아니라 바이트! 웹에서 파일(특히 이미지와 같은 미디어 파일)을 전송할 때, 이 파일들은 기본적으로 바이트 데이터로 존재한다. 하지만 HTTP를 통해 데이터를 전송할 때는 문자열 형태로 전송되는 것이 일반적. 따라서 바이트 형태의 이미지 데이터를 안전하게 문자열로 변환하여 전송하고, 받는 쪽에서는 이 문자열을 다시 원래의 바이트 데이터로 변환해야 한다. 이 과정에서 Base64 인코딩 방식이 자주 사용 된다! 이미지 파일을 바이트 배열로 읽어옴 -> 바이트 배열을 Base64로 인코딩하여 문자열로 변환 -> 변환된 문자열을 HTTP를 통해 전송 -> Base64로 인코딩된 문자열 데이터를 받음 -> 문자열을 Base64 디코딩하여 원래의 바이트 배열로 변환 -> 바이트 배열을 사용하여 이미지 파일을 복원하거나 필요한 작업을 수행 그걸 MultipartFile imgFile = requestDTO.getImgFile(); 이 객체가 알아서 해준다! 사진은 바이트!!!
notion image
notion image
 
💡
DB에는 내 서버 측의 파일 경로만 넣을 것!
 

파일 쓰기 - 이 코드의 목적 : static 폴더 안에 사진 뿌리기

notion image
사용자가 웹 애플리케이션을 통해 파일을 업로드하면, 서버는 이 파일을 받아 static 폴더 같은 정적 리소스를 제공하는 디렉토리에 저장한다. 실제 파일을 서버의 하드디스크에 저장하고, 그 파일의 경로나 이름은 데이터베이스(DB)에 저장 -> 파일 자체가 아니라 경로나 파일명만 저장하는 이유는 데이터베이스에 실제 파일 데이터를 저장하는 것이 비효율적이고 성능에 부정적인 영향을 줄 수 있기 때문
 

 
notion image
DB에는 이거 2개(title과 imgFilename)만 저장할 것이다!
notion image
@Controller public class PicController { @PostMapping("/upload") public String upload(PicRequest.UploadDTO requestDTO) { String title = requestDTO.getTitle(); MultipartFile imgFile = requestDTO.getImgFile(); String imgFilename = imgFile.getOriginalFilename(); //맛집.png가 될 것 Path imgPath = Paths.get(imgFilename); //이렇게 path를 만듬 // Path imgPath = Paths.get("a/"+imgFilename); //경로가 a라는 폴더 안에 있으면 이런 식으로 함 try { Files.write(imgPath, imgFile.getBytes()); //파일의 내용을 바이트 배열로 읽어옴 } catch (IOException e) { throw new RuntimeException(e); } return "redirect:/"; }
💡
Path imgPath = Paths.get(imgFilename); -> 경로 설정하는 코드
파일의 경로나 이름은 데이터베이스(DB)에 저장하기 때문에 경로를 설정하는 코드가 필요
 

[ 화면 확인 ]

notion image
사진 업로드를 했는데... 오잉? 이상한 곳에 들어가버렸다. -> 경로 이상 여기에 들어가버리면 html 폴더에서 찾을 수가 없다. html에서 찾으려면 'static 폴더' 안에 무조건 있어야한다!
 

[ 외울 필요 없이 짧게 테스트만 해보자. 프로젝트에 따라 다 다름 ]

경로 앞에 [ / ] 를 붙이면?

Path imgPath = Paths.get("/" + imgFilename);
💡
제---일 최상위 경로로 들어왔다.. 즉, \D: 드라이브에 들어가 있다.
 

경로 앞에 [ ./ ] 를 붙이면? ( ./ = 현재 경로)

Path imgPath = Paths.get("./" + imgFilename);
💡
fileapp 폴더 내부로 들어왔다.
💡
./했는데 study_lec에서 실행되고 있다면 현재 경로는 study_lec이란 말이다
 

[ static 경로에 넣기 ]

Path imgPath = Paths.get("./src/main/resources/static/" + imgFilename);
💡
왜 static에 넣을까? → 애만 외부에서 접근이 가능하기 때문 다른 폴더를 쓰고 싶으면 그 폴더를 외부에 노출할 수 있게 스프링에서 따로 설정을 해줘야함
notion image
💡
들어왔다!
 

[ upload 경로에 넣기 ]

notion image
Path imgPath = Paths.get("./src/main/resources/static/upload/" + imgFilename);
notion image
 

 
static 폴더는 외부에서 파일명으로 바로 접근 가능하기 때문에 uploadCheck.mustache 에서 <img src="/upload/hello.png" width="500" height="500" alt="사진없음"> 라고 쓴다.

그러니까

<img src="/upload/{{fileName}}" width="500" height="500" alt="사진없음"> fileName 이 부분만 DB에서 들고 오자. 안그러면 DB에 전부 UPDATE 쳐서 수정해야함
notion image
 

파일명을 다르게 전송해야 한다

고객이 hello와 hello 파일을 2개 저장해버리면 ... 안됨 그래서 롤링이 필요하다. (hello1이나 hello2 처럼 저장되는...) -> 해쉬가 필요하다!!! 해쉬맵으로 저장한다!
 
Share article

codingb