스프링프레임웍 ajax 파일업로드 - jQuery, FormData, jQuery Form Plugin 사용

프로그래밍/스프링프레임워크 2018. 4. 4. 21:40
반응형

이 글에서는 스프링 프레임웍 환경에서 ajax를 통한 파일 업로드 방법을 알아 보겠습니다.


서버와의 ajax 통신에는 jQuery를 사용하고 업로드를 위해서 FormData 객체를 사용하는 방법과 jQuery Form Plugin 을 사용하는 방법을 알아 보겠습니다. 전체소스는 하단에 첨부 되어 있습니다.  jQuery Form Plugin 은 https://github.com/jquery-form/form 에서 다운로드 받을 수 있습니다.


두 가지 방법의 차이점은 다음과 같습니다.


- FormData를 사용하는 경우 : Internet Explorer 10이상 부터 사용할 수 있습니다.

- jQuery Form Plugin을 사용하는 경우는 IE10 이하에서도 사용할 수 있지만 문제를 일으키는 경우도 있습니다.



이제 코드를 보도록 하겠습니다.


1. 파일 업로드를 위한 Multipart Resolver를 설정합니다. root-context.xml 파일입니다.

 

<bean name="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10000000"></property>
</bean>

 

2. 업로드 후 응답을 json 데이터로 보내기 위한 View Resolver 를 설정합니다. servlet-context.xml 파일입니다.

 

<beans:bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
    <beans:property name="contentType" value="application/json;charset=UTF-8" />
</beans:bean>

 

3. JSON 객체를 사용하기 위한 디펜던시를 추가합니다. pom.xml 파일입니다. 

 

<!-- json-simple -->
<dependency>
    <groupId>com.googlecode.json-simple</groupId>
    <artifactId>json-simple</artifactId>
    <version>1.1</version>
</dependency>

 

4. 요청 처리를 위한 컨트롤러 입니다. HomeController.java 파일 입니다.

 

package com.tistory.pentode;

import java.io.File;
import java.util.Iterator;
import java.util.List;

import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

/**
 * 파일업로드를 처리합니다.
 */
@Controller
public class HomeController {
	
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
    // 업로드된 파일이 저장될 위치 입니다.
    private final String PATH = "C:/workspace/workspace_neon/spring_upload/src/main/webapp/WEB-INF/upload/";
	
    // json 데이터로 응답을 보내기 위한 
    @Autowired
    MappingJackson2JsonView jsonView;
	
    @RequestMapping(value = "/uploadForm.do")
    public String uploadForm() throws Exception {
	return "uploadForm";
    }
	
    @RequestMapping(value="/upload.do", method=RequestMethod.POST, produces="text/plain")
    public ModelAndView upload(MultipartHttpServletRequest request) throws Exception {
		
        // 응답용 객체를 생성하고, jsonView 를 사용하도록 합니다.
	ModelAndView model = new ModelAndView();
	model.setView(jsonView);
		
	Iterator itr =  request.getFileNames();
		
        if(itr.hasNext()) {
            List mpf = request.getFiles(itr.next());
            // 임시 파일을 복사한다.
            for(int i = 0; i < mpf.size(); i++) {

                File file = new File(PATH + mpf.get(i).getOriginalFilename());
                logger.info(file.getAbsolutePath());
                mpf.get(i).transferTo(file);
                
            }
            
            // 업로드된 파일이 있을경우 응답입니다.
            JSONObject json = new JSONObject();
            json.put("code", "true");
            model.addObject("result", json);
            return model;
            
        } else {
        	
            // 파일이 없을 경우 응답 입니다.
            JSONObject json = new JSONObject();
            json.put("code", "false");
            model.addObject("result", json);
            return model;
            
        }
    }
}

 


5. 파일업로드 폼 html 입니다. 두 개의 파일 선택필드와 업로드 버튼으로 구성되어 있습니다. uploadForm.jsp 파일 입니다.

 

<div>
<form id="uploadForm" enctype="multipart/form-data" method="POST" action="/pentode/upload.do">
    <label for="file1">파일 첫 번째</label>
    <div><input type="file" id="file1" name="file" required="required" /></div>
    <label for="file2">파일 두 번째</label>
    <div><input type="file" id="file2" name="file" required="required" /></div>
</form>
</div>

<div><button id="btn-upload">파일 업로드</button></div>

 

6. 업로드 처리를 위한 JavaScript 부분입니다. 먼저 FormData 를 이용하는 방법입니다. 이 경우는 IE 10 이상에서 동작합니다.

 

<script src="<c:url value="/js/jquery-3.1.0.min.js"/>"></script>
<script type="text/javascript">
//<![CDATA[
$(function() {
  $("#btn-upload").on("click", function(){
    var form = new FormData(document.getElementById('uploadForm'));
    $.ajax({
      url: "/pentode/upload.do", //컨트롤러 URL
      data: form,
      dataType: 'json',
      processData: false,
      contentType: false,
      type: 'POST',
      success: function (response) {
        alert("success");
        console.log(response);
      },error: function (jqXHR) {
	alert(jqXHR.responseText);
      }
    });
  });
});
//]]>
</script>

 

7. jQuery Form Plugin 을 사용하는 방법입니다.

 

<script src="<c:url value="/js/jquery-3.1.0.min.js"/>"></script>
<script src="<c:url value="/js/jquery.form.min.js"/>"></script>
<script type="text/javascript">
//<![CDATA[
$(function() {

  $("#btn-upload").on("click", function(){
    $('#uploadForm').ajaxSubmit({
	url: "/pentode/upload.do", //컨트롤러 URL
	dataType: 'json',
	processData: false,
	contentType: false,
	type: 'POST',
	success: function (response) {
	  alert("success");
	  console.log(response);
	},error: function (jqXHR) {
	  alert(jqXHR.responseText);
	}
    });
  });
});
//]]>
</script>

 

8. jQuery Form Plugin을 사용시 IE9 이하에서 응답 정보가 파일로 다운로드 되어 버리는 경우가 있습니다. 이때에는 응답의 컨텐츠 타입을 'text/plain' 으로 설정합니다.

 

<beans:bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
	<beans:property name="contentType" value="text/plain;charset=UTF-8" />
</beans:bean>

 

9. 실행 결과 입니다.


실행결과




이것으로 스프링 프레임웍에서 ajax 통신으로 파일을 업로드 하는 방법을 알아 보았습니다. 이 예제는 업로드하는 방법을 보여주기 위한 뼈대만을 가진 예제 입니다. 파일 업로드를 실제 적용하기 위해서는 다음과 같은 추가 사항이 필요할 것입니다.


- 파일 I/O, 데이터베이스등의 예외 사항 처리.

- 업로드된 파일 정보를 데이터베이스에 저장.

- 파일 저장위치 설정파일로 옮기기

- 파일 확장자 체크(보안 목적으로 업로드 할 수 있는 파일 타입을 제한)

- 업로드된 파일명의 변경(보안 목적 및 파일명 중복 방지)


※ 전체소스


반응형

댓글을 달아 주세요