본문 바로가기
프로그래밍/스프링프레임워크

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

by pentode 2018. 4. 4.

이 글에서는 스프링 프레임웍 환경에서 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, 데이터베이스등의 예외 사항 처리.

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

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

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

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

 

※ 전체소스

 

반응형