파일 업로드 기능은 웹 애플리케이션에서 중요한 기능 중 하나입니다. 이번 글에서는 Spring Boot를 사용하여 파일 업로드 기능을 구현하는 방법을 설명합니다. 또한 업로드한 파일을 유니크한 파일명으로 저장하고, 허용된 파일 확장자만 업로드할 수 있도록 제한하는 방법도 함께 다루겠습니다.
1. 프로젝트 설정
1.1 의존성 추가
먼저, pom.xml 파일에 파일 업로드를 처리할 수 있는 의존성을 추가해야 합니다. Spring Boot에서는 파일 업로드 기능을 처리할 수 있는 기본적인 지원을 제공하지만, spring-boot-starter-web 의존성이 필요합니다.
<dependencies>
<!-- Spring Boot Web 의존성 추가 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 파일 업로드 처리를 위한 Multipart 의존성 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
1.2 application.properties 설정
파일 업로드 디렉토리와 허용할 파일 확장자를 application.properties에서 설정할 수 있습니다.
# 파일 저장 디렉토리
file.upload-dir=C:/upload
# 허용된 파일 확장자 (쉼표로 구분)
file.allowed-extensions=jpg,png,txt,pdf
2. Controller 코드
이제 파일 업로드를 처리하는 FileUploadController를 작성합니다. 업로드된 파일은 UUID를 사용해 고유한 이름으로 저장하고, 허용된 확장자만 업로드할 수 있도록 제한합니다.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
@Controller
public class FileUploadController {
// application.properties에서 설정된 값 읽기
@Value("${file.upload-dir}")
private String uploadDir;
@Value("${file.allowed-extensions}")
private String allowedExtensions;
// 기본 페이지를 반환하는 메서드
@RequestMapping("/upload")
public String upload() {
return "upload";
}
// 파일 업로드 처리 메서드
@PostMapping("/upload")
public String uploadFiles(@RequestParam("files") MultipartFile[] files, Model model) {
if (files.length == 0) {
model.addAttribute("message", "파일을 선택하세요!");
return "upload";
}
List<String> uploadedFiles = new ArrayList<>();
List<String> failedFiles = new ArrayList<>();
List<String> rejectedFiles = new ArrayList<>();
// 허용된 확장자 목록을 ',' 기준으로 분리하여 리스트로 변환
List<String> allowedList = Arrays.asList(allowedExtensions.split(","));
for (MultipartFile file : files) {
if (!file.isEmpty()) {
String fileName = file.getOriginalFilename();
if (fileName == null) continue;
// 파일 확장자 추출
String fileExtension = getFileExtension(fileName);
// 허용된 확장자 확인
if (!allowedList.contains(fileExtension.toLowerCase())) {
rejectedFiles.add(fileName);
continue;
}
// 유니크한 파일명 생성 (UUID)
String uniqueFileName = UUID.randomUUID().toString() + "." + fileExtension;
try {
String filePath = Paths.get(uploadDir, uniqueFileName).toString();
File dest = new File(filePath);
file.transferTo(dest);
uploadedFiles.add(uniqueFileName); // 업로드된 파일의 유니크한 이름 저장
} catch (IOException e) {
failedFiles.add(fileName);
}
}
}
if (!uploadedFiles.isEmpty()) {
model.addAttribute("message", "업로드 성공: " + String.join(", ", uploadedFiles));
}
if (!failedFiles.isEmpty()) {
model.addAttribute("error", "업로드 실패: " + String.join(", ", failedFiles));
}
if (!rejectedFiles.isEmpty()) {
model.addAttribute("reject", "허용되지 않은 확장자: " + String.join(", ", rejectedFiles));
}
return "upload";
}
// 파일 확장자 추출 메서드
private String getFileExtension(String fileName) {
int lastIndex = fileName.lastIndexOf(".");
if (lastIndex == -1) {
return ""; // 확장자가 없는 경우
}
return fileName.substring(lastIndex + 1);
}
}
코드 설명
- @Value 어노테이션을 사용하여 application.properties에서 설정된 값(upload-dir과 allowed-extensions)을 읽어옵니다.
- UUID를 사용하여 업로드된 파일에 고유한 이름을 부여합니다.
- getFileExtension() 메서드를 통해 업로드된 파일의 확장자를 추출하고, 허용된 확장자인지 확인합니다.
- 허용되지 않은 확장자는 업로드되지 않으며, 실패한 파일은 failedFiles 리스트에 저장됩니다.
3. 업로드 폼 (HTML)
src/main/resources/templates/upload.html에 업로드 폼을 작성합니다. 이 폼에서는 여러 파일을 한 번에 선택할 수 있도록 multiple 속성을 사용합니다.
<!DOCTYPE html>
<html>
<head>
<title>파일 업로드</title>
</head>
<body>
<h2>파일 업로드</h2>
<form method="POST" enctype="multipart/form-data" action="/upload">
<input type="file" name="files" multiple required>
<input type="file" name="files" multiple required>
<button type="submit">업로드</button>
</form>
<div>
<h3>결과</h3>
<p th:if="${message}" th:text="${message}"></p>
<p th:if="${error}" th:text="${error}"></p>
<p th:if="${reject}" th:text="${reject}"></p>
</div>
</body>
</html>
업로드 폼 설명
- multipart/form-data로 폼을 설정하여 파일 데이터를 서버에 전송합니다.
- 사용자가 파일을 선택하고 업로드 버튼을 클릭하면 파일이 서버로 전송됩니다.
4. 실행 및 테스트
4.1 애플리케이션 실행
이제 애플리케이션을 실행하여 파일 업로드 기능을 테스트할 수 있습니다.
mvn spring-boot:run
브라우저에서 http://localhost:8080을 열어 파일을 업로드해보세요. 업로드한 파일은 C:/upload 경로에 유니크한 이름으로 저장됩니다. 또한, 허용되지 않은 확장자의 파일은 업로드되지 않습니다.
5. 마무리
이번 글에서는 Spring Boot를 사용하여 파일 업로드 기능을 구현하고, 업로드된 파일을 유니크한 파일명으로 저장하는 방법을 다뤘습니다. 또한 허용된 파일 확장자만 업로드할 수 있도록 제한하는 방법도 함께 구현했습니다. 이 기능은 파일 업로드 시 이름 충돌을 방지하고, 보안을 강화하는 데 유용하게 사용될 수 있습니다.
📚 관련 자료
'개발 > Spring' 카테고리의 다른 글
| Spring Boot & Maven Scope (compile, provided, runtime 등 차이점) (0) | 2025.02.13 |
|---|---|
| Spring Boot에서 파일 업로드 구현하기(Ajax File upload) (0) | 2025.02.13 |
| Spring Validation 어노테이션, 구현 방법 (0) | 2025.02.13 |
| [Spring Boot] Environment, @Value, @ConfigurationProperties (0) | 2025.02.12 |
| Spring Boot Actuator 개요 (0) | 2025.02.12 |