728x90
반응형
00. Validator
- 스프링에서 범용적으로 사용할 수 있는 object 검증기를 정의할 수 있는 API
▷ support() : 검증기가 검증할 수 있는 object타입인지 확인해주는 메소드
▷ validate() : target 객체에 대한 검증을 실행하는 메소드, 검증결과에 문제가 있을 경우에는 errors 객체에 에러정보 저장
package com.mvc.updown.validate;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
//@Service도 가능
@Component
public class FileValidator implements Validator {
@Override
public boolean supports(Class<?> clazz) {
return false;
}
@Override
public void validate(Object target, Errors errors) {
UploadFile file = (UploadFile)target;
if(file.getMpfile().getSize() == 0) { // empty 라면
//(Field, errorCode, defaultMessage)
errors.rejectValue("mpfile", "fileNPE", "Please select a file");
}
}
}
01. uploadFile
▶︎ 입출력 다시보기
- input(입력) : 데이터를 입력받을 때
- output(출력) : 데이터가 나갈 때
▶︎ applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
</beans>
▶︎ HomeController.java : 세부 설명은 코드 내 주석으로 대체
package com.mvc.updown;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.WebUtils;
import com.mvc.updown.validate.FileValidator;
import com.mvc.updown.validate.UploadFile;
@Controller
public class HomeController {
@Autowired
private FileValidator fileValidator;
@RequestMapping("/form")
public String uploadForm() {
return "upload";
}
@RequestMapping("/upload")
public String fileUpload(HttpServletRequest request, Model model,
UploadFile uploadFile, BindingResult result) {
// bindingResult는 validate를 기다리다가 에러가 나면 그 다음 갈 경로를 안내해주고,
// form:errors 와 연결해준다.
// bindingResult는 Error를 상속받고 있기 때문에 validate에 Error result로 들어갈 수 있음.
// target 객체에 대한 검증(binding을 할 수 있는지?)을 실행하는 메소드
fileValidator.validate(uploadFile, result);
// 에러가 있으면 되돌아 감
if(result.hasErrors()) {
return "upload";
}
// 전달받은 uploadFile의 mpfile을 있는 MultipartFile에 담아준다.
// MultipartFile : 사용자가 업로드한 file을 핸들러에서 쉽게 다룰 수 있도록 도와주는 handler 매개변수 중 하나
// MultipartResolver bean이 등록되어 있어야 한다.
MultipartFile file = uploadFile.getMpfile();
// 파일의 원본 이름을 담아준다.
String name = file.getOriginalFilename();
// 새로 만든 uploadFile객체에 원본이름과 원본desc를 담아준다.
// download.jsp로 보내주기 위해
UploadFile fileObj = new UploadFile();
fileObj.setName(name);
fileObj.setDesc(uploadFile.getDesc());
InputStream inputStream = null; // input : 데이터가 들어올 때
OutputStream outputStream = null; // output : 데이터가 나갈 때
try {
// 전달받은 uploadFile의 내용을 읽어들이고 stream에 담아준다.
inputStream = file.getInputStream();
// 저장 실제경로를 찾아서 담아준다.
String path = WebUtils.getRealPath(request.getSession().getServletContext(), "/resources/storage");
System.out.println("업로드될 실제 경로(real path): " + path);
// 담은 실제 경로에 /resources/storage 라는 경로를 만들기 위해 파일생성자를 새로 만든다.
File storage = new File(path);
// 파일이 존재하지 않는다면 새로 디렉토리를 만들어 준다.
if(!storage.exists()) {
storage.mkdirs(); // mkdirs: 상위 경로까지 만들어주고, mkdir: 없으면 안만들고
}
// 원본이름으로 파일을 새로 만들어 준다.
File newFile = new File(path + "/" + name);
if(!newFile.exists()) {
newFile.createNewFile();
}
// 그 파일을 담아서 output한다.
outputStream = new FileOutputStream(newFile);
int read = 0;
byte[] b = new byte[(int) file.getSize()];
// .read: 읽은 바이트들을 매개값으로 배열b에 저장하고 실제로 읽은 바이트 수를 리턴
// 파일의 개수만큼 b[0] ~ b[n-1]까지 돌면서 file을 input해준다.
while((read=inputStream.read(b)) != -1) { // 마지막파일이면 -1 , 파일이 없으면 0
// 바이트 배열 b에서 b[0]~b[read]까지의 바이트를 보낸다.내보내 주어 저장
outputStream.write(b, 0, read);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
inputStream.close();
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 이거는 화면에 뿌려주기 위한 정보를 담아서 보내준다.
model.addAttribute("fileObj", fileObj);
return "download";
}
@RequestMapping("/download")
@ResponseBody
public byte[] fileDownload(HttpServletRequest request,
HttpServletResponse response, String name) throws IOException {
byte[] down = null;
String path;
try {
path = WebUtils.getRealPath(
request.getSession().getServletContext(), "/resources/storage");
File file = new File(path + "/" + name);
down = FileCopyUtils.copyToByteArray(file);
// "8859_1"로 한글 파일명 처리
String filename = new String(file.getName().getBytes(), "8859_1");
// Content-Disposition : attachment -> file download 설정(filename을 지정 가능)
// 이렇게 지정해주면 응답받았을 때 이게 file형태라는 것을 인식할 수 있음
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
response.setContentLength(down.length);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return down;
}
}
▶︎ upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form:form method="post" enctype="multipart/form-data"
modelAttribute="uploadFile" action="upload">
<h3>upload form</h3>
file<br>
<input type="file" name="mpfile"/><br>
<p style="color:red; font-weight: bold;">
<form:errors path="mpfile"></form:errors>
</p><br>
<textarea rows="10" cols="60" name="desc"></textarea>
<input type="submit" value="send"/>
</form:form>
</body>
</html>
form tag의 enctype 속성
1. application/www-form-urlencoded : (default) 문자들이 encoding 됨
2. multipart/form-data : file upload 할 때 사용(post),
그렇지 않으면 웹서버로 데이터를 넘길때 파일의 경로명만 전송되고 파일내용이 전달되지 않는다
3. text/plain : encoding 하지 않음
- spring form : tag
- form:form, form:input, form:errors, ...
- form:errors = Errors, BindingResult클래스를 사용할 때,
command객체의 특정 field에서 발생하는 에러메세지 출력 가능
▶︎ download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
file: ${fileObj.name }<br>
desc: ${fileObj.desc }<br>
<form action="download" method="post">
<input type="hidden" name="name" value="${fileObj.name }"/>
<input type="submit" value="download"/>
</form>
tomcat web.xml 아래쪽 mime-type(Multipurpose Internet Mail Extension)
: request header에 지정되는 데이터가 어떤 종류의 stream인지를 나타내는 프로토콜
mime-type 추가
<mime-mapping>
<extension>hwp</extension>
<mime-type>application/unknown</mime-type>
</mime-mapping>
728x90
반응형
'Web > Spring' 카테고리의 다른 글
[Spring]MVC_08.jdbc_lamda(익명함수) (0) | 2020.11.07 |
---|---|
[Spring]MVC_07.update (0) | 2020.11.07 |
[Spring]MVC_05.security (0) | 2020.11.06 |
[Spring]MVC_04.Interceptor, Transaction (0) | 2020.11.05 |
[Spring]MVC_3.로그인 (0) | 2020.11.05 |