스프링 MVC 2편
Intro
안녕하세요. 최혜정 사원입니다. 스프링 MVC 2편 강의를 보고 정리한 내용입니다.
1. 파일 업로드
보통 파일 업로드를 위해서 HTML Form을 이용한다.
폼을 전송하는 2가지 방법
- application/x-www-form-urlencoded
- multipart/form-data
application/x-www-form-urlencoded
- 가장 기본적인 방법이다.
- 단순 text 보낼 때 사용한다.
- 폼에 전송할 항목을 HTTP Body에 문자로 &로 구분해서 전송한다.
multipart/form-data
- 다른 종류의 여러 파일과 폼의 내용을 함께 전송할 수 있다.
- text와 binary 데이터를 같이 보내야 하는 경우처럼 여러 타입의 데이터를 함께 보내야 하는 경우 사용한다.
- 각각의 항목을 구분해서 한번에 전송하는 것이다.
- Content-Disposition이라는 항목별 헤더가 추가되어 있고 여기에 부가 정보가 있다.
- 파일의 경우 파일 이름과 Content-Type이 추가되고, 바이너리 데이터가 전송된다.
2. 서블릿과 파일 업로드
@Slf4j
@Controller
@RequestMapping("/servlet/v1")
public class ServletUploadControllerV1 {
@GetMapping("/upload")
public String newFile() {
return "upload-form";
}
@PostMapping("/upload")
public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {
log.info("request={}", request);
String itemName = request.getParameter("itemName");
log.info("itemName={}", itemName);
Collection<Part> parts = request.getParts();
log.info("parts={}", parts); // multipart/form-data방식에서 각각 나누어진 부분을 받아 확인할 수 있다.
return "upload-form";
}
}
2-1. 서블릿과 파일 업로드2
실제 파일이 저장되는 경로
application.properties
file.dir=/Users/kimyounghan/study/file/
- 주의: 경로는 ‘/’으로 시작하고 끝내야 한다.
@Slf4j
@Controller
@RequestMapping("/servlet/v2")
public class ServletUploadControllerV2 {
@Value("${file.dir}")
private String fileDir;
//spring의 value 사용해야 함
@GetMapping("/upload")
public String newFile() {
return "upload-form";
}
@PostMapping("/upload")
public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {
String itemName = request.getParameter("itemName");
Collection<Part> parts = request.getParts();
for (Part part : parts) {
log.info("==== PART ====");
log.info("name={}", part.getName());
// Parts의 헤더와 바디 구분
Collection<String> headerNames = part.getHeaderNames();
for (String headerName : headerNames) {
log.info(headerName, part.getHeader(headerName));
}
// 편의 메서드
// content-dispositon, file-name
log.info(part.getSubmittedFileName()); // 클라이언트가 전달한 파일명
log.info("size={}", part.getSize());
// part body size
// 데이터 읽기(body에 있는 데이터 읽기)
InputStream inputStream = part.getInputStream(); // part의 전송 데이터를 읽을 수 있다.
String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); // utf-8로 바꿈
// 바디 읽은걸 String으로
// 바이너리와 문자간의 변경에는 char 제공해줘야함
log.info(body);
// 파일에 저장하기
if (StringUtils.hasText(part.getSubmittedFileName())) {
String fullPath = fileDir + part.getSubmittedFileName();
log.info("파일 저장 fullPath={}", fullPath);
part.write(fullPath); // 편리하게 저장 가능
}
}
return "upload-form";
}
}
- application.properties에서 설정한 file.dir의 값을 주입
- @Value 어노테이션으로 application.properties에 있는 값을 필드값으로 지정해줄 수 있다
@Value("${file.dir}")
private String fileDir;
- 전송 데이터를 하나하나 각각 부분(Part)으로 나누어 전송한다.
3. 스프링과 파일 업로드
스프링은 MultipartFile 이라는 인터페이스로 멀티파트 파일을 매우 편리하게 지원한다.
file.getOriginalFilename() : 업로드 파일 명
file.transferTo(…) : 파일 저장
@RequestMapping("/spring")
public class SpringUploadController {
@Value("${file.dir}")
private String fileDir;
@GetMapping("/upload")
public String newFile() {
return "upload-form";
}
@PostMapping("/upload")
public String saveFile(@RequestParam String itemName, @RequestParam MultipartFile file, HttpServletRequest request) throws IOException {
log.info("request={}", request);
log.info("itemName={}", itemName);
log.info("multipartFile={}", file);
if (!file.isEmpty()) {
String fullPath = fileDir + file.getOriginalFilename();
log.info("파일 저장 fullPath={}", fullPath);
file.transferTo(new File(fullPath));
}
return "upload-form";
}
}
- 파일 정보들은 @RequestParam을 통해 쿼리파라미터 처럼 MultipartFile 타입으로 입력된다.
- 파일의 이름값을 얻어오고, File 객체를 만들고, 파일을 저장하게 된다.
Leave a comment