Posts 스프링 파일업다운로드
Post
Cancel

스프링 파일업다운로드

[spring] 파일 업/다운로드

HTML 폼 전송 방식

HTML에서 폼을 전송하는 방식(Content-Type)에는 다음 두가지가 있다.

  • application/x-www-form-urlencoded : 문자와 같은 데이터를 키와 함께 전송하는 방식

    • ex) username=Kim&age=20
  • multipart/form-data : 여러 개의 데이터를 파트별로 나누어 전송하는 방식. 파일과 같은 바이너리 데이터를 전송할 때 쓰임.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    Content-Type: multipart/form-data; boundary=------XXX
    
    ------XXX
    Content-Disposition: form-data; name="username"
    
    kim
    ------XXX
    Content-Disposition: form-data; name="age"
    
    20
    ------XXX
    Content-Disposition: form-data; name="file"; filename="intro.png"
    Content-Type: Image/png
    
    [이미지 바이너리 데이터]
    ------XXX--
    


파일 업로드

서블릿 파일 업로드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@PostMapping("/upload")
public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {
	Collection<Part> parts = request.getParts();		// 멀티파트 데이터 가져오기

	for (Part part : parts) {
      //데이터 읽기
      InputStream inputStream = part.getInputStream();
    	String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

      //파일에 저장하기
      if (StringUtils.hasText(part.getSubmittedFileName())) {
      	String fullPath = fileDir + part.getSubmittedFileName(); 		// 클라이언트가 전달한 파일명
				part.write(fullPath);		// 주어진 위치에 저장
			}
  }
	return "upload-form";
}

request.getPart()를 통해 멀티파트 데이터를 가져오고, 각 파트별로 part.write() 메서드를 사용하면 인자로 넣은 주소에 저장된다.

하지만 위와 같은 방법은 ` HttpServletRequest`를 인자로 받아와야하며, 파일을 각자 구분하기 위해 여러 코드를 넣어야한다.


스프링 파일 업로드

1
2
3
4
5
6
7
8
9
@PostMapping("/upload")
public String saveFile(@RequestParam String itemName, @RequestParam MultipartFile file) throws IOException {

	if (!file.isEmpty()) {
		String fullPath = fileDir + file.getOriginalFilename(); // 파일 원제목 가져오기
		file.transferTo(new File(fullPath)); // 주어진 위치로 파일 저장
	}
	return "upload-form";
}

스프링에서는 멀티파트 파일을 저장하기 위핸 MultipartFile를 제공한다. 따라서 매개변수의 이름을 들어올 파일의 이름과 맞춰준다면 자동으로 해당 매개변수에 파일을 넣어준다.

다음과 같이 @ModelAttribute를 사용하여 받을 수도 있다.

1
2
3
4
5
6
7
8
9
// MultipartFile
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class MultipartTest {
	private String itemName;
	private MultipartFile file;
}
1
2
@PostMapping("/upload")
public String saveFile(@ModelAttribute MultipartTest item) // work


파일 다운로드

이미지 다운로드

<img> 태그로 조회 시 내려주는 방법. UrlResource로 이미지 파일을 읽어서 body에 넣어 반환한다.

1
2
3
4
5
@ResponseBody
@GetMapping("/images/{filename}")
public Resource downloadImage(@PathVariable String filename) throws MalformedURLException {
	return new UrlResource("file:" + fileStore.getFullPath(filename));
}

파일 다운로드

Content-Disposition 헤더에 attachment; filename="파일 이름" 값을 넣고, UrlResource를 body에 담아 내려준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@GetMapping("/attach/{itemId}")
public ResponseEntity<Resource> downloadAttach(@PathVariable Long itemId) throws MalformedURLException {
  	// db에 저장된 파일 데이터 가져오기.
		Item item = itemRepository.findById(itemId);
		String storeFileName = item.getAttachFile().getStoreFileName();
		String uploadFileName = item.getAttachFile().getUploadFileName();

		UrlResource resource = new UrlResource("file:" + fileStore.getFullPath(storeFileName));

		String encodedUploadFileName = UriUtils.encode(uploadFileName, StandardCharsets.UTF_8);

		return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_DISPOSITION,
              "attachment; filename=\"" + encodedUploadFileName + "\"")
			.body(resource);
	}

이미지 다운로드 때와 다른 점은 Content-Disposition 헤더가 설정되었다는 점이다.

Content-Disposition은 HTTP response body에 오는 컨텐츠의 기실/성향을 알려주는 속성으로, default 값은 web에 전달되는 data라고 생각하면된다.

특수한 경우는 Content-Disposition에 attachment를 주는 경우로, 이때 filename과 함께 주면 body에 오는 값을 다운로드 받으라는 뜻이 된다.

https://lannstark.tistory.com/8


스프링 멀티파트 설정

다음과 같이 application.properties에서 멀티파트 데이터에 관한 설정을 할 수 있다.

1
2
3
4
5
6
# 한 파일의 최대 용량
spring.servlet.multipart.max-file-size=5MB
# 한 multipart 요청의 최대 크기
spring.servlet.multipart.max-request-size=10MB
# multipart 처리를 할 것인가. (false 시 멀티파트 데이터를 처리하지 않음)
spring.servlet.multipart.enabled=true

출처

김영한의 스프링 MVC 강의 2편

This post is licensed under CC BY 4.0 by the author.

Spring 파라미터 Validation

blue-green 배포

Comments powered by Disqus.