스프링 MVC 2편

최혜정

Updated:

Intro

안녕하세요. 최혜정 사원입니다. 스프링 MVC 2편 강의를 보고 정리한 내용입니다.

1. 파일 업로드

보통 파일 업로드를 위해서 HTML Form을 이용한다.

폼을 전송하는 2가지 방법

  1. application/x-www-form-urlencoded
  2. multipart/form-data

application/x-www-form-urlencoded

  • 가장 기본적인 방법이다.
  • 단순 text 보낼 때 사용한다.
  • 폼에 전송할 항목을 HTTP Body에 문자로 &로 구분해서 전송한다.

text전송

multipart/form-data

  • 다른 종류의 여러 파일과 폼의 내용을 함께 전송할 수 있다.
  • text와 binary 데이터를 같이 보내야 하는 경우처럼 여러 타입의 데이터를 함께 보내야 하는 경우 사용한다.
  • 각각의 항목을 구분해서 한번에 전송하는 것이다.

multipart

  • 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)으로 나누어 전송한다.

결과로그1

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