반응형
File Upload
파일 업로드
- 클라이언트가 서버로 파일을 전송하는 과정
- 여러 개의 파일을 업로드 할 수 있음
기존 방식의 Form
- 기존에 사용하던 <form>은 문자 위주의 데이터를 사용
- enctype="application/x-www-form-urlencoded" 기본 값(생략 가능)
- HTTP Body에 문자로 key=value 형태로 전송하고, 여러 개의 데이터라면 & 기호를 통해 구분하였음
파일 업로드 방식의 Form
- 파일은 문자가 아닌 바이너리 데이터를 전송
- 파일만 전송하는 것이 아니라 다른 데이터를 같이 전송하기도 함
- enctype="multipart/form-data", method="POST" 필수
- 여러 개의 파일을 업로드하고 싶다면 multiple="multiple" 속성 추가 필요
참고할 블로그
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 |