프로젝트/Springboot_MariaDB
[Springboot_MariaDB_thymleaf] 웹페이지에서 이미지 업로드, DB에 저장, 이미지 다운로드
CBJH
2024. 6. 13. 10:19
728x90
반응형
@Controller // Spring MVC 컨트롤러임을 나타내는 어노테이션
public class FileController {
@Autowired // FileService 의존성 자동 주입
private FileService fileService;
@GetMapping("/") // 루트 경로("/")에 대한 GET 요청 처리
public String index(Model model) {
// 모든 파일 목록 조회하여 모델에 추가
List<FileEntity> files = fileService.getAllFiles();
model.addAttribute("files", files);
// index 템플릿 렌더링
return "index";
}
@PostMapping("/upload") // "/upload" 경로에 대한 POST 요청 처리 (파일 업로드)
public String uploadFile(@RequestParam("file") MultipartFile file, Model model) {
try {
// FileService를 통해 파일 저장
fileService.saveFile(file);
} catch (IOException e) {
e.printStackTrace(); // 예외 발생 시 로그 출력
}
// 루트 경로로 리다이렉트 (파일 목록 페이지로 이동)
return "redirect:/";
}
@GetMapping("/download/{id}") // "/download/{id}" 경로에 대한 GET 요청 처리 (파일 다운로드)
public ResponseEntity<byte[]> downloadFile(@PathVariable Long id) {
// id에 해당하는 파일 조회, 없으면 예외 발생
FileEntity fileEntity = fileService.getFile(id)
.orElseThrow(() -> new RuntimeException("File not found"));
// ResponseEntity를 사용하여 파일 데이터와 헤더 정보를 함께 반환
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileEntity.getFileName() + "\"") // 파일 다운로드 헤더 설정
.body(fileEntity.getData()); // 파일 데이터 설정
}
}
클래스 기능:
- 사용자에게 파일 업로드 및 다운로드 기능을 제공하는 컨트롤러입니다.
- 업로드된 파일 정보는 FileService를 통해 관리됩니다.
- / 경로로 접근하면 파일 목록을 보여주는 페이지가 나타납니다.
- /upload 경로로 파일을 업로드할 수 있습니다.
- /download/{id} 경로를 통해 특정 파일을 다운로드할 수 있습니다.
package com.example.demo; // 패키지 선언
import jakarta.persistence.*;
import lombok.Data;
// JPA 엔티티 클래스로, 데이터베이스의 "files" 테이블과 매핑
@Entity
@Table(name = "files")
@Data // Lombok 어노테이션으로 getter, setter, toString 등 자동 생성
public class FileEntity {
// 기본 키 (Primary Key) 설정, 자동 증가
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// "file_name" 컬럼과 매핑, 파일 이름 저장
@Column(name = "file_name")
private String fileName;
// "data" 컬럼과 매핑, BLOB 타입으로 파일 데이터 저장
@Lob // Large Object 저장을 위한 어노테이션
@Column(name = "data", columnDefinition = "LONGBLOB")
private byte[] data;
// Lombok @Data에 의해 자동 생성됨
// getters and setters
}
클래스 기능:
- 데이터베이스에 파일 정보를 저장하기 위한 엔티티 클래스입니다.
- files 테이블의 각 레코드는 하나의 FileEntity 객체에 매핑됩니다.
- 각 파일은 고유한 id, fileName (파일 이름), data (파일 데이터)를 가집니다.
주요 필드:
- id: 각 파일의 고유 식별자이며, 데이터베이스에서 자동으로 생성됩니다.
- fileName: 파일의 원본 이름을 저장합니다.
- data: 파일의 실제 내용(바이너리 데이터)을 저장합니다. @Lob 어노테이션은 큰 용량의 데이터를 저장하기 위해 사용됩니다.
@Repository
public interface FileRepository extends JpaRepository<FileEntity, Long> {
}
package com.example.demo; // 패키지 선언
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
// 비즈니스 로직을 처리하는 서비스 계층임을 나타내는 어노테이션
@Service
public class FileService {
// FileRepository 의존성 자동 주입
@Autowired
private FileRepository fileRepository;
// MultipartFile 형태의 파일을 저장하는 메서드
public FileEntity saveFile(MultipartFile file) throws IOException {
// FileEntity 객체 생성
FileEntity fileEntity = new FileEntity();
// 파일의 원본 이름과 데이터를 설정
fileEntity.setFileName(file.getOriginalFilename());
fileEntity.setData(file.getBytes());
// 데이터베이스에 저장하고 저장된 FileEntity 객체 반환
return fileRepository.save(fileEntity);
}
// id에 해당하는 파일을 조회하는 메서드
public Optional<FileEntity> getFile(Long id) {
// 데이터베이스에서 조회 (결과는 Optional로 감싸서 반환)
return fileRepository.findById(id);
}
// 모든 파일 목록을 조회하는 메서드
public List<FileEntity> getAllFiles() {
// 데이터베이스에서 전체 파일 목록 조회
return fileRepository.findAll();
}
}
클래스 기능:
- 파일 업로드 및 다운로드와 관련된 비즈니스 로직을 처리하는 서비스 클래스입니다.
- MultipartFile 형태의 파일을 FileEntity 객체로 변환하여 데이터베이스에 저장합니다.
- FileRepository를 통해 데이터베이스에서 파일 정보를 조회합니다.
- 컨트롤러에서 호출되어 파일 관련 작업을 수행합니다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="post" enctype="multipart/form-data" th:action="@{/upload}">
<input type="file" name="file" />
<button type="submit">Upload</button> </form>
<h2>Uploaded Files</h2> <ul>
<li th:each="file : ${files}">
<a th:href="@{/download/{id}(id=${file.id})}" th:text="${file.fileName}"></a>
</li>
</ul>
</body>
</html>
코드 설명:
- Thymeleaf 네임스페이스 선언 (xmlns:th): Thymeleaf 템플릿 엔진을 사용하기 위한 네임스페이스를 설정합니다.
- 파일 업로드 폼 (<form>):
- method="post": 파일 업로드는 POST 방식으로 처리되어야 합니다.
- enctype="multipart/form-data": 파일 데이터를 포함한 폼 데이터를 전송하기 위한 필수 속성입니다.
- th:action="@{/upload}": Thymeleaf 표현식을 사용하여 파일 업로드를 처리하는 컨트롤러의 /upload 엔드포인트로 폼을 제출하도록 설정합니다.
- <input type="file" name="file" />: 사용자가 파일을 선택할 수 있도록 하는 파일 입력 필드입니다. name="file"은 서버에서 파일 데이터를 받을 때 사용할 이름을 지정합니다.
- 업로드된 파일 목록 (<ul>):
- th:each="file : ${files}": Thymeleaf의 반복 처리 구문으로, files 리스트에 있는 각 파일(file)에 대해 <li> 요소를 생성합니다.
- <a th:href="@{/download/{id}(id=${file.id})}" th:text="${file.fileName}"></a>:
- th:href: 각 파일을 다운로드하기 위한 링크를 생성합니다. Thymeleaf 표현식을 사용하여 /download/{id} 경로에 파일 ID를 동적으로 삽입합니다.
- th:text: 링크의 텍스트를 파일 이름(file.fileName)으로 설정합니다.
전체 동작:
- 사용자가 파일을 선택하고 "Upload" 버튼을 클릭하면 폼이 제출됩니다.
- 폼 데이터는 /upload 엔드포인트를 처리하는 컨트롤러로 전송됩니다.
- 컨트롤러는 파일을 저장하고 파일 목록 페이지로 리다이렉트합니다.
- 파일 목록 페이지는 files 모델 속성에 저장된 업로드된 파일 목록을 가져와 Thymeleaf를 사용하여 각 파일의 다운로드 링크를 생성하고 표시합니다.