스프링 프레임워크에서 다중 파일업로드 예
스프링에서 업로드를 위한 설정은 우측 링크를 눌러 참조하세요. 여기를 클릭하세요.
WEB-INF/views/upload/uploadForm.jsp
<%@ page 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>파일 업로드 폼</title>
</head>
<body>
<form:form method="post" enctype="multipart/form-data"
modelAttribute="uploadVO" action="fileUpload">
파일에 대한 설명:
<form:input path="desc" type="text"/><br>
업로드할 파일 선택:
<%--uploadVO객체 안에 files 변수가 존재해야 한다 --%>
<form:errors path="files" style="color:red;"/><br>
<input name="files[0]" type="file"/>
<input name="files[1]" type="file"/><br>
<input name="files[2]" type="file"/><br>
<button type="submit">전 송</button><br>
</form:form>
</body>
</html>UploadController.java
package org.dodream.java;
import java.io.*;
import java.util.List;
import javax.servlet.http.*;
import org.dodream.model.UploadVO;
import org.dodream.service.FileValidator;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.validation.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.*;
import org.springframework.web.servlet.*;
@Controller
public class UploadController
{
@Autowired
private FileValidator fileValidator;
@RequestMapping(value="/upload/form", method=RequestMethod.GET)
public String getUploadForm (
@ModelAttribute("uploadVO") UploadVO uploadVO )
{ /*위에서 지정한 uploadVO 키는 폼이 처음 화면에 보일 때 폼의 각 필드가
request 영역에 저장된 UploadVO와 연결되어 오류가 발생하는 것을
막기 위한 것으로 POST 방식 요청을 처리하는 아래의 메소드와는 무관하다 */
return "upload/uploadForm";
}
/*@ModelAttribute("uploadVO") UploadVO uploadVO 는 브라우저에서 전송되는 파라미터를
Model 객체에 uploadVO 라는 이름으로 저장한다는 것을 의미한다. Model 에 저장된 데이터는 내부에서
request 객체에 저장되므로 뷰에서 접근할 수 있게 된다 */
@RequestMapping(value="/upload/fileUpload", method=RequestMethod.POST)
public ModelAndView fileUploaded(
@ModelAttribute("uploadVO") UploadVO uploadVO,
BindingResult result)
{
fileValidator.validate(uploadVO, result);
if (result.hasErrors()) {
return new ModelAndView("upload/uploadForm");
}
// 업로드된 파일을 지정된 경로로 이동한다
List<MultipartFile> list = uploadVO.getFiles();
System.out.println("파일의 갯수:"+list.size());
InputStream inputStream = null;
OutputStream outputStream = null;
//다수개의 파일을 업로드하는 경우 처리하는 예
for(int i=list.size()-1;i>=0;i--)
{
MultipartFile file = list.get(i);
// 파일의 내용이 비어 있는 경우에는 리스트에서 삭제한다
if(file.getSize()==0) {
list.remove(i);
continue;
}
String fileName = file.getOriginalFilename();
try {
inputStream = file.getInputStream();
File newFile = new File("D:/upload/" + fileName);
if (!newFile.exists()) {
newFile.createNewFile();
}
outputStream = new FileOutputStream(newFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(inputStream!=null) inputStream.close();
if(outputStream!=null) outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new ModelAndView("upload/uploadResult");
}
@RequestMapping("/upload/download")
@ResponseBody
public byte[] getImage(HttpServletResponse response,
@RequestParam String filename) throws IOException
{
File file = new File("D:/upload/"+filename);
byte[] bytes = org.springframework.util.FileCopyUtils.copyToByteArray(file);
//한글은 http 헤더에 사용할 수 없기때문에 파일명은 영문으로 인코딩하여 헤더에 적용한다
String fn = new String(file.getName().getBytes(), "iso_8859_1");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fn + "\"");
response.setContentLength(bytes.length);
response.setContentType("image/jpeg");
return bytes;
}
}UploadVO.java
package org.dodream.model;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public class UploadVO
{
private String desc;
private List<MultipartFile> files;
// 위의 files변수에 파일정보를 전달하기 위해서는 폼에서 다음과 같이 해야한다
// <input type="file" name="files[0]">
// <input type="file" name="files[1]">
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public List<MultipartFile> getFiles() {
return files;
}
public void setFiles(List<MultipartFile> files) {
this.files = files;
}
}FileValidator.java
package org.dodream.service;
import java.util.List;
import org.dodream.model.UploadVO;
import org.springframework.stereotype.*;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.multipart.MultipartFile;
@Service("fileValidator")
public class FileValidator implements Validator
{
public boolean supports(Class<?> arg0) {
return false;
}
public void validate(Object obj, Errors errors)
{
UploadVO vo = (UploadVO) obj;
List<MultipartFile> list = vo.getFiles();
boolean valid = false;
//한개의 파일이라도 업로드된 경우에는 유효성검사에 통과한 것으로 한다
for(int i=0;i<list.size();i++){
if(list.get(i).getSize()!=0){
valid = true;
};
}
if(!valid){
errors.rejectValue("files", "UploadForm.SelectFile",
"한개의 파일은 꼭 선택해야 합니다!");
// 메시지 리소스 파일을 사용하는 경우에는 UploadForm.SelectFile.files 키에
// 등록된 오류 메시지가 우선적으로 사용되고 그렇지 않으면 위에서 처럼 디폴트 메시지로 지정된
// 오류 메시지가 뷰로 전달된다. 뷰에서는 spring 태그를 사용하여
// <form:errors path="files"/>
}
}
}WEB-INF/views/upload/uploadResult.jsp
<%@ page 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>파일 업로드 결과</title>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
function download(fname){
$("#filename").val(fname);
$("#downloadForm").submit();
}
</script>
</head>
<body>
<h2>업로드된 파일 정보</h2>
<c:forEach var="f" items="${requestScope.uploadVO.files}">
파일명 : ${f.originalFilename}
<a href="javascript:download('${f.originalFilename}');">다운로드</a>
<br>
</c:forEach>
<form id="downloadForm" action="download" method="post">
<input type="hidden" id="filename" name="filename">
</form>
</body>
</html>