Spring Boot에서 base64로 이미지 업로드,다운로드 기능 구현하기
Base64 : 이진데이터를 텍스트(ASCII)로 바꾸거나 (인코딩) 반대 과정(디코딩) 을 처리하는 방법 중 하나이다. 이진 데이터는 6비트씩 묶이는 반면에 ASCII 문자는 8비트로 표현되기 때문에 인코딩 과정 후 텍스트 데이터는 원래 데이터보다 크기가 약 33% 증가한다.
Board에 byte[] mediaData 엔티티 추가
@Lob
@Column(name = "mediaData", columnDefinition="LONGBLOB")
private byte[] mediaData;
public void setMediaData(MultipartFile file) {
try {
this.mediaData = file.getBytes(); // 이미지 파일을 byte 배열로 변환하여 저장
} catch (IOException e) {
e.printStackTrace();
}
}
MultipartFile 객체에 getBytes()메소드를 호출하면 파일의 바이트를 추출할 수 있다.
BoardService > saveImg 수정
public void saveImg(Board board, MultipartFile file) throws Exception {
String projectPath = System.getProperty("user.dir") + "/src/main/webapp/files";
String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename(); // 파일 이름을 랜덤으로 생성
String filePath = Paths.get(projectPath, fileName).toString(); // 파일 경로 설정
// 이미지 파일을 디스크에 저장
Files.copy(file.getInputStream(), Paths.get(projectPath).resolve(fileName), StandardCopyOption.REPLACE_EXISTING);
// 엔티티에 파일 이름과 경로 설정
board.setFilename(fileName);
board.setFilepath("/files/" + fileName);
boardRepository.save(board);
}
java.nio.file.Files.copy(Path source, Path target, CopyOption... options) : 파일을 복사하여 /src/main/webapp/files 에 저장한다.
BoardController > boardwritepro 수정
@PostMapping("/board/writepro")
public String boardWritePro(Board board, Model model, @RequestParam("file") MultipartFile file) {
try {
// 이미지 파일을 byte 배열로 변환하여 엔티티에 저장
board.setMediaData(file);
boardService.write(board);
boardService.saveImg(board,file);
// 게시글과 이미지 정보를 저장
boardService.write(board);
model.addAttribute("message", "글 작성이 완료되었습니다.");
model.addAttribute("searchUrl", "/board/list");
return "message";
} catch (Exception e) {
model.addAttribute("error", "[ERROR] : 글 작성에 실패했습니다. 이미지 파일 형식이 올바르지 않을 수도 있습니다.");
return "error";
}
}
@RequestParam : 클라이언트가 웹 애플리케이션에 HTTP 요청을 보낼 때 URL에 포함된 쿼리 문자열이나 POST 요청의 바디에 포함된 데이터를 가져올 때 쓰인다.
예를 들어, 다음과 같은 URL이 있다고 가정: http://example.com/api/user?id=123&name=John
이 경우, @RequestParam을 사용하여 id와 name 파라미터 값을 가져올 수 있다.
BoardController > boardview 수정
@GetMapping("/board/view") // localhost:8080/board/view?id=1
public String boardView(Model model, Integer id){
Board board = boardService.boardView(id);
String base64Image = null;
if (board.getMediaData() != null) {
base64Image = Base64.getEncoder().encodeToString(board.getMediaData());
}
model.addAttribute("board", board);
model.addAttribute("base64Image", base64Image);
return "boardview";
}
Base64.getEncoder()를 사용하여 데이터를 인코딩할 수 있으며, 그 결과로 Base64.Encoder 객체를 얻을 수 있다. 이 객체는 encodeToString(byte[]) 및 encode(byte[])와 같은 메서드를 호출하여 바이트 배열을 Base64 문자열로 인코딩할 수 있다.
boardview.html에 img 태그 추가
<img th:unless="${base64Image}==''"
th:src="'data:image;base64,' + ${base64Image}"
alt="이미지" />
th:unless는 타임리프의 조건문 문법으로 base64Image가 빈 값이 아니라면 이미지를 화면상에 출력해준다.