DEVELOPMENT/Spring

[스프링부트 완전정복] 7. 파일 업로드 처리

Tiny Commit 2025. 11. 10. 12:13

 

 

 

 

 

1. 파일 업로드 개요

  • 파일 업로드: 파일을 웹 브라우저에 서버로 전송하여 저장하는 것
  • 텍스트 파일, 바이너리 파일, 이미지 파일, 문서 파일
  • 웹 페이지에서 폼태그를 사용하고, 파일을 서버로 업로드.

1. 파일 업로드를 위한 설정

  • 별도의 라이브러리 추가 없이 application.properties파일에 설정
spring.servlet.multipart.enabled=true			# 멀티 파트 업로드 지원 여부
spring.servlet.multipart.file-size-threshold=2KB	# 파일이 메모리에 기록되는 임계값
spring.servlet.multipart.location=C:/upload		# 업로드된 파일의 임시 저장 공간
spring.servlet.multipart.max-file-size=200MB		# 파일의 최대 크기
spring.servlet.multipart.max-request-size=215MB		# 요청의 최대 크기

 

2. 파일 업로드를 위한 웹 페이지

  • 웹페이지 -> 서버로 전송하는 폼페이지
    • Method는 POST
    • enctype은 multipart/form-data
    • action은 실행 파일
    • type은 file설정
<form method="post" enctype="multipart/form-data" action="viewPage_process.html">
    <p>제목 : <input type="text" name="title"></p>
    <p>파일 : <input type="file" name="fileName"></p>
    <p><input type="submit" value="submit"></p>
</form>

 

3. 정적 리소스 위치 설정하기

  • ResourceHttpRequestHandler 클래스: 파일 시스템 접근
    • /static
    • /public
    • /resources
    • /META-INF/resources
  • ResourceHandlerRegistry : 정적 리소스가 저장된 WAR, 파일 시스템 접근
    • WAR: 리소스가 저장됨.
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            .addResourceHandler("/resources/**") //외부 URI
            .addResourceLocations("/resources/"); //실제 리소스 경로
    }
}

 

 

 

 

 

 

2. MultupartFile을 이용한 파일 업로드 처리

1. MultipartFile을 이용한 파일 업로드 처리

  • 업로드된 파일과 파일 데이터를 표현할 때 사용
  • 단일, 다중 업로드 가능
메서드 타입 설명
getName() String 멀티 파트 폼에서 파라미터 이름을 반환
getContentType() String 파일의 콘텐츠 형식을 반환
getOriginalFilename() String 클라이언트의 파일 시스템에서 실제 파일 이름을 반환
isEmpty() boolean 업로드한 파일의 존재 여부를 반환
getSize() long 바이트의 파일 크기를 반환
getBytes() byte[] 바이트의 배열로 파일 내용을 반환
getInputStream() InputStream 파일 폼의 내용을 읽어 InputStream으로 반환
transferTo(File dest) void 전송된 파일을 지정한 대상 파일로 전송

 

 

2. 파일 업로드 유형

 

MultipartFileServletRequest 인터페이스 이용하기

  • 우선 HttpServletRequest(getParameter()), MultipartRequest(getFile()) 인터페이스를 상속받아야 한다. 
  • 요청 전체를 받아 필요한 파라미터와 파일을 직접 꺼내야 합니다. (request.getParameter(), request.getFile())
@Controller
@RequestMapping("/exam01")
public class Example01Controller {

    @GetMapping("/form")
    public String requestForm() {
        return "viewPage";
    }

    @PostMapping("/form")
    public String submitForm(MultipartHttpServletRequest request, Model model) {
        // 1. 폼 페이지의 요청 파라미터 name의 값을 전송받습니다.
        String name = request.getParameter("name");
        
        // 2. 폼 페이지의 요청 파라미터 fileImage의 파일을 전송받습니다.
        MultipartFile file = request.getFile("fileImage");
        
        String filename = file.getOriginalFilename();
        File saveFile = new File("C:\\upload\\" + name + "_" + filename);

        try {
            // 3. 파일을 업로드합니다.
            file.transferTo(saveFile);
            
            model.addAttribute("data1", "MultipartHttpServletRequest 예제");
            model.addAttribute("data2", filename);
            model.addAttribute("data3", saveFile.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "viewPage_process";
    }
}

 

 

@RequestParam

  • 멀티 파트 요청이 들어오면 @RequestParam과 MultipartFile 타입의 매개변수를 사용해야 한다. 
  • 파일을 포함한 각 폼 데이터를 @RequestParam을 이용해 개별적으로 필요한 타입(String, MultipartFile)으로 주입받음.
@Controller
@RequestMapping("/exam02")
public class Example02Controller {

    @GetMapping("/form")
    public String requestForm() {
        return "viewPage";
    }

    @PostMapping("/form")
    public String submitForm(
        @RequestParam("name") String name, 
        @RequestParam("fileImage") MultipartFile file, 
        Model model
    ) {
        String filename = file.getOriginalFilename();
        // C:\\upload\\ 경로와 파일 이름 사이에 "_"가 추가된 것
        File saveFile = new File("C:\\upload\\" + name + "_" + filename); 

        try {
            // 파일 업로드
            file.transferTo(saveFile);
            
            model.addAttribute("data1", "@RequestParam 예제");
            model.addAttribute("data2", filename);
            model.addAttribute("data3", saveFile.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "viewPage_process";
    }
}

 

 

 

 

@ModelAttribute

  • 매개변수와 동일한 이름으로 커맨드 객체 내에 MultipartFile타입의 프로퍼티를 추가합니다. 
  • 요청 메서드는 @ModelAttribute를 선언하여 업로드할 파일을 포함한 요청 파라미터를 전송받음.
  • 폼 데이터와 파일을 객체(Member 클래스)로 한 번에 묶어 받고 싶을 때 사용합니다.
// 커맨드 객체
package com.springboot.domain;

import org.springframework.web.multipart.MultipartFile;
import lombok.Data; // Lombok Data 어노테이션 사용

@Data // Getter, Setter, toString 등을 자동 생성
public class Member {

    private String name;
    private MultipartFile fileImage;
}

 

//컨트롤러
...
import com.springboot.domain.Member; // 커맨드 객체 import
import java.io.File;
import java.io.IOException;

@Controller
@RequestMapping("/exam03")
public class Example03Controller {

    @GetMapping("/form")
    public String requestForm(Member member) { // @ModelAttribute가 적용
        return "viewPage";
    }

    @PostMapping("/form")
    public String submitForm(@ModelAttribute Member member, Model model) {
        // 1. 폼 페이지의 요청 파라미터 name의 값을 전송받습니다.
        String name = member.getName();
        
        // 2. 폼 페이지의 요청 파라미터 fileImage의 파일을 전송받습니다.
        MultipartFile file = member.getFileImage();
        
        String filename = file.getOriginalFilename();
        File saveFile = new File("C:\\upload\\" + name + "_" + filename);

        try {
            // 3. 파일을 업로드합니다.
            file.transferTo(saveFile);
            
            model.addAttribute("data1", "@ModelAttribute 예제");
            model.addAttribute("data2", filename);
            model.addAttribute("data3", saveFile.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "viewPage_process";
    }
}

 

 

 

외부 파일 시스템 접근 설정

package com.springboot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class ResourceConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            // URL 패턴: "/images/**"로 요청이 오면
            .addResourceHandler("/images/**")
            // C 드라이브의 "/upload/" 디렉토리에서 파일을 찾습니다.
            .addResourceLocations("file:///C:/upload/");
    }
}

 

 

 

 

 

3. [도서 쇼핑몰 도서 이미지 업로드 처리하기]

1. 정적 리소스로 이미지와 부트스트랩 관리하기

  • 정적 리소스 관리 폴더 생성 (src/main/resource/static)
  • 도서 클래스 멤버 변수 추가 (Book.java)
  • 도서 데이터 저장소 클래스 수정 (BookRepositoryImpl)
  • 도서 목록 페이지 수정 (books.html)
  • 도서 상세 정보 페이지 수정 (book.html)

2. 도서 이미지 업로드하기

  • 도서 이미지 파일의 저장 위치 생성
  • 파일 업로드 저장 위치 설정 (application.properties)
  • 파일 시스템에 저장된 이미지에 접근하는 클래스 생성 (ResourceConfig 클래스 생성)
  • 도서 클래스에 멤버 변수 추가 (Book.java)
  • 도서 이미지 파일 업로드 (BookController)
  • 도서 등록 페이지 수정 (addBook.html)

3. 이미지 파일 다운로드

  • 도서 이미지 파일 다운로드 (BookController)
  • 도서 정보 상세 페이지 수정 (book.html)

 

 

 

 

 

 

 

 


 


연습문제

더보기

01.다음 중 파일 업로드를 위한 폼 태그의 규칙으로 옳지 않은 것은?

 

02.다음 중 파일을 업로드하는 방법으로 사용되는 클래스(또는 인터페이스)로 옳은 것은?

 

03.다음 중 컨트롤러에 멀티 파트 요청으로 들어오는 업로드된 파일 데이터를 전달받기 위해 MultipartFile 인터페이스와 함께 사용할 수 있는 애너테이션으로 옳은 것은?

 

04.다음 중 MultipartHttpServletRequest에서 MultipartFile 데이터를 전달받는 메서드로 옳은 것은?

 

05.다음 중 MultipartFile 인터페이스의 메서드에 대한 설명으로 옳지 않은 것은?

 

06.다음 중 1에 지정하는 클래스로 옳은 것은?

 

07.다음 중 2에 지정하는 파일을 업로드하는 메서드로 옳은 것은?

 

08.다음 중 앞의 예제에 따라 application.properties 파일에 업로드할 파일의 저장 경로 설정에 해당하는 구문으로 옳은 것은?

 

09.다음 중 앞의 예제에 따라 application.properties 파일에 업로드할 파일의 최대 크기를 200MB로 설정하는 구문으로 옳은 것은?

 

10.다음 중 앞의 예제에 따라 윈도우 운영체제에서 빈칸에 들어가는 정적 리소스 위치 설정에 해당하는 구문으로 옳은 것은?

 

 

 


 


출처 : 송미영, 『 스프링부트 완전정복: 개념부터 실정 프로젝트까지 』길벗캠퍼스 (2024).