스프링 mvc - 파일 업로드

meluu_·2024년 2월 1일
0

스프링

목록 보기
27/27
post-thumbnail

🌿 시작하기 앞서


스프링 부트 3.2.1 버전을 기준으로 작성됨

파일 업로드에서 HTML Form으로 데이터 전송할 때

단순히 문자만 전송하는 것이 아닌 파일 즉 바이너리 데이터를, 심지어 문자와 같이 전송하게 된다면 어떻게 처리해야할까?

-> Http의multipart/form-data 라는 전송 방식 제공
데이터의 각 항목을 구분에서 한 번에 전송

Form 태크에 enctype="multipart/form-data"를 지정해야함

multipart/form-data 는 매우 복잡하고 각각의 부분(Part)로 나누어져 있다.
이러한 HTTP 메시지를 서버에서 어떻게 사용할 수 있을까?



🌱 서블릿과 파일 업로드


 @PostMapping("/upload")
 public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {

//getParts() : multipart/form-data 전송 방식에서 
//             각각 나누어진 부분을 반환
Collection<Part> parts = request.getParts();
//...
}

<form th:action method="post" enctype="multipart/form-data">
 <ul>
 <li>상품명 <input type="text" name="itemName"></li>
 <li>파일<input type="file" name="file" ></li>
 </ul>
 <input type="submit"/>
 </form>

멀티파트 사용 옵션

업로드 사이즈 제한
//application.properties
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=10MB
multipart 처리 제한
//application.properties
// 멀티파트 처리 작동하지 않는다.
spring.servlet.multipart.enabled=false // default = true

출력

// 폼 데이터에 맞게 입력 및 파일 전송시 
request=org.springframework.web.multipart.support.StandardMultipartHttpServletRequest
itemName=Spring
parts=[ApplicationPart1, ApplicationPart2]

HttpServletRequest 객체가
RequestFacade -> StandardMultipartHttpServletRequest로 변환

spring.servlet.multipart.enabled true시 DispatcherServlet 에서 멀티파트 리졸버를 실행
해당 리졸버는 멀티파트 요청인 경우 HttpServletRequest -> MultipartHttpServletRequest로 변환하여 반환



✔️ 실제 파일 서버 업로드


// application.properties
file.dir=파일 업로드 경로 설정 (): /Users/user/mvc/file/

* 1. 꼭 해당 경로에 실제 폴더 존재해야함
* 2. 마지막에 / 포함해야 함
// application.properties에서 설정 값 주입
@Value("${file.dir}")
private String fileDir;

    @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);


        for (Part part : parts) {
            log.info("==== PART ====");
            log.info("name={}", part.getName());
            Collection<String> headerNames = part.getHeaderNames();
            for (String headerName : headerNames) {
                log.info("header {}: {}", headerName, part.getHeader(headerName));
            }

            //편의 메서드
            // content=disposition; filename
            log.info("submittedFilename={}", part.getSubmittedFileName());
            log.info("size={}", part.getSize()); // part Body size

            // 데이터 읽기
            InputStream inputStream = part.getInputStream();
            String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
            log.info("body={}", body);

            // 파일 저장하기
            if (StringUtils.hasText(part.getSubmittedFileName())) {
                String fullPath = fileDir + part.getSubmittedFileName();
                log.info("파일 저장 fullPath={}", fullPath);
                part.write(fullPath);
            }
        }

        return "upload-form";
    }
}

결과

Part 주요 메서드

part.getSubmittedFileName() : 클라이언트가 전달한 파일명
part.getInputStream(): Part의 전송 데이터를 읽을 수 있다.
part.write(...): Part를 통해 전송된 데이터를 저장할 수 있다.



✔️ 스프링 파일 업로드



@Value("${file.dir}")
private String fileDir;
 
 
@PostMapping("/upload")
public String saveFile(@RequestParam String itemName,
                           @RequestParam MultipartFile file, HttpServletRequest request) throws IOException {
                           
	if (!file.isEmpty()) {
		String fullPath = fileDir + file.getOriginalFilename();
		log.info("파일 저장 fullPath={}", fullPath);
		file.transferTo(new File(fullPath));
	}                                                  
}

@RequestParam MultipartFile file
업로드하는 HTML Form의 name에 맞추어 @RequestParam 을 적용

MultipartFile 주요 메서드

file.getOriginalFilename(): 업로드 파일 명
file.transferTo(...): 파일 저장



🔖 학습내용 출처

스프링 MVC 2편 - 백엔드 웹 개발 활용 기술

profile
열심히 살자

0개의 댓글