Spring 3/Multiple File Upload

Spring Framework Multiple File Upload example

Soul-Learner 2017. 4. 6. 15:16

스프링 프레임워크에서 다중 파일업로드 예


스프링에서 업로드를 위한 설정은 우측 링크를 눌러 참조하세요. 여기를 클릭하세요.


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>