나를 기록하다
article thumbnail
Published 2024. 3. 19. 08:55
[TIL-46/240318] File Upload & Download TIL
반응형

File Upload

파일 업로드

  • 클라이언트가 서버로 파일을 전송하는 과정
  • 여러 개의 파일을 업로드 할 수 있음

 

기존 방식의 Form

  • 기존에 사용하던 <form>은 문자 위주의 데이터를 사용
  • enctype="application/x-www-form-urlencoded" 기본 값(생략 가능)
  • HTTP Body에 문자로 key=value 형태로 전송하고, 여러 개의 데이터라면 & 기호를 통해 구분하였음

 

파일 업로드 방식의 Form

  • 파일은 문자가 아닌 바이너리 데이터를 전송
  • 파일만 전송하는 것이 아니라 다른 데이터를 같이 전송하기도 함
  • enctype="multipart/form-data", method="POST" 필수
  • 여러 개의 파일을 업로드하고 싶다면 multiple="multiple" 속성 추가 필요

참고할 블로그

파일업로드 & 다운로드1

파일업로드 & 다운로드2

 

MultipartFile

  • Spring Framework에서 파일 업로드를 처리하기 위한 인터페이스
  • 파일의 내용은 메모리에 저장되거나, 디스크에 임시로 저장
  • 사용자가 원하는대로 세션수준 또는 영구 저장소에 파일의 내용을 복사할 책임
    • 세션 수준(Session Level): 웹 애플리케이션에서 데이터의 유효 범위를 나타내는 용어 중 하나입니다. 세션 수준은 데이터가 세션 동안 유지되는 기간
  • 임시 저장소는 요청이 끝나면 삭제
  • getOriginalFilename(): 업로드 파일명
  • transferTo(): 파일저장

 

파일 업로드 추가 설정

  • servlet-context.xml 파일에 Multipart를 처리하기 위한 Resolver 등록
    • servlet-context: web과 관련된 정보 등록
  • StandardServletMultipartResolver → MultipartResolver의 구현체 중 하나 Spring MVC 권장
<beans:bean id="multipartResolver"
	class="org.springframework.web.multipart.support.StandardServletMultipartResolver"></beans:bean>
  • tomcat의 context.xml에서 allowCasualMultipartParsing="true"을 작성
  • 용량의 기본은 1MB / web.xml에서 용량을 지정 가능
<multipart-config>
    <max-file-size>10485760</max-file-size>
    <max-request-size>20971520</max-request-size>
</multipart-config>

 

실습

controller

import java.io.File;
import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class MainController {

	//파일이나 클래스 경로 등 리소스를 로드하는데 사용하는 인터페이스
	private final ResourceLoader resourceLoader;

	@Autowired //생성자가 하나일 때는 @Autowired 생략 가능
	public MainController(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}
	
	@GetMapping("/")
	public String index() {
		return "index";
	}

	@GetMapping("/singleFileForm")
	public String singleFileForm() {
		return "singleFileForm";
	}

	@PostMapping("/singleFileUpload")
	public String singleFileUpload(@RequestParam("file") MultipartFile file, Model model) throws IllegalStateException, IOException {
		//파일 있는지 검사, 용량이 없으면 등록하지 않겠다
		if(file != null && file.getSize() > 0) {
			String fileName = file.getOriginalFilename();
			System.out.println(fileName);
			Resource resource = resourceLoader.getResource("resources/upload");
			file.transferTo(new File(resource.getFile(), fileName));
			model.addAttribute("fileName", fileName);
		}
		return "result";
	}
	
	@GetMapping("/download")
	public String download(@RequestParam("fileName") String fileName, Model model) {
		model.addAttribute("fileName", fileName);
		return "fileDownloadView";
	}
}

 

view

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class FileDownloadView extends AbstractView {

	private final ResourceLoader resourceLoader;

	@Autowired
	public FileDownloadView(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
		setContentType("application/download; charset=UTF-8");
	}

	// 컨트롤러에서 뷰로 데이터를 전달하는 메서드
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		String fileName = (String) model.get("fileName");
		Resource resource = resourceLoader.getResource("resources/upload");
		File file = new File(resource.getFile(), fileName);
		///////////////////////////////////////////////////////////
		// 파일 다운로드 설정
		response.setContentType(getContentType());
		response.setContentLength((int) file.length());

		fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1"); // 한글 방식을 안전하게 처리할 수 있게 해줌
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
		response.setHeader("Content-Transfer-Encoding", "binary");

		////////////////////////////////////////////////////////////

		try (FileInputStream fis = new FileInputStream(file); OutputStream os = response.getOutputStream()) {
			FileCopyUtils.copy(fis, os);
		}
	}
}

 

WEB-INF/views

singleFileForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>단일 파일 업로드</title>
</head>
<body>
	<h2>단일 파일 업로드</h2>
	<form action="singleFileUpload" method="POST" enctype="multipart/form-data">
		<input type="file" name="file">
		<input type="submit" value="파일 등록">
	</form>
</body>
</html>

 

multiFileForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>다중 파일 업로드</title>
</head>
<body>
	<h2>다중 파일 업로드</h2>
	<form action="multiFileUpload" method="POST" enctype="multipart/form-data">
		<input type="file" name="file" multiple="multiple">
		<input type="submit" value="파일 등록">
	</form>
</body>
</html>

 

result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>단일 파일 업로드</title>
</head>
<body>
	<h2>단일 파일 업로드</h2>

	<a
		href="${pageContext.request.contextPath }/resources/upload/${fileName}">${fileName }</a>
	<img
		src="${pageContext.request.contextPath }/resources/upload/${fileName}">

	<a href="download?fileName=${fileName }">${fileName } 다운로드</a>
</body>
</html>

반응형

'TIL' 카테고리의 다른 글

[TIL-48/240320] DDL & DML  (0) 2024.03.21
[TIL-47/240319] MySQL, SELECT  (0) 2024.03.20
[TIL-45/240315] MVC 패턴  (0) 2024.03.16
[TIL-44/240314] Filter & Interceptor  (2) 2024.03.15
[TIL-43/240313] Spring MVC  (1) 2024.03.13
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...