서버에는 업로드와 관련해서 다음과 같은 여러 작업이 이루어 진다.
- 사용자가 업로드 하는 시간에 따른 자동적인 폴더 생성
- 업로드 되는 파일의 고유한 이름 생성
- 이미지 파일의 업로드 시 썸네일 이미지 (웹 페이지의 작은 이미지 파일)를 생성
- 이미지 파일의 경우 서버에서 저장된 파일을 읽어서 적당한 MIME 타입으로 서비스
- 일반 파일의 경우 다둔로드 타입으로 파일 데이터 서비스
이미지 파일의 경우에는 이미지를 깨끗하게 축소할 수 있는 imgScalr 라이브러리를 활용한다.
imgScalr 라이브러리는 큰 이미지 파일을 고정된 크기로 변환할때 편리하다.
* 라이브러리 설정
http://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
Imgscalr A Java Image Scaling Library
<!-- https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib --> <dependency> <groupId>org.imgscalr</groupId> <artifactId>imgscalr-lib</artifactId> <version>4.2</version> </dependency>
스프링에서 multipartResolver 라고 하는 이 객체의 설정은 웹과 관련 있기 때문에 root-context.xml 이 아닌 servlet-context.xml 을
이용해서 설정한다.
servlet-context.xml
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <beans:property name="maxUploadSize" value="10485760" /> </beans:bean>
서버의 파일 저장 경로 설정
파일을 저장할 경로는 상수처럼 사용되기 때문에 servlet-context.xml 파일을 이용해서 특정 경로를 문자열로 설정한다.
1.
<!-- 서버의 파일 저장 경로 설정 --> <beans:bean id="uploadPath" class="java.lang.String"> <beans:constructor-arg value="/resources/upload" /> </beans:bean>
2. 실제 서버내 리눅스 주소를 입력 해라
<!-- 서버의 파일 저장 경로 설정 --> <beans:bean id="uploadPath" class="java.lang.String"> <beans:constructor-arg value="d:\\dev\\upload" /> </beans:bean>
FileCopyUtils 는 파일 데이터를 파일로 처리하거나, 복사하는 등의 작업에 유용하게 사용될 수 있다. FileCopyUitls 클래스의 모든 static 메소드는
copy 이고, 다음과 같은 방식들이 제공된다.
주요 static 메소드 설명
copy(byte[] in, File out ) 데이터가 담긴 바이트의 배열(in) 을 파일에 기록한다.
copy(byte[] in, OutputStream out) 데이터가 담긴 바이트의 배열(in) 을 특정한 OutputStream 으로 전송한다.
copy(InputStream in, OutputStream out) 특정한 InputStream 을 특정한 OutputStream 으로 전송한다.
copy(String in, Writer out) 문자열을 그대로 Writer 를 이용해서 기록한다.
cpyToByteArray(InputStream in) 주어진 InputStream 을 읽어서 byte[] 로 만들어 반환한다.
1. 기본적인 파일 업로드 방식
UploadController
package test.controller; import java.io.File; import java.util.UUID; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; @Controller public class UploadController { private static final Logger logger = LoggerFactory.getLogger(UploadController.class); @Resource(name="uploadPath") private String uploadPath; @RequestMapping(value="/test/uploadForm", method=RequestMethod.GET) public void uploadForm() throws Exception{ } @RequestMapping(value="/test/uploadForm", method=RequestMethod.POST) public void uploadForm(MultipartFile file, Model model ) throws Exception{ logger.info("originalName : " + file.getOriginalFilename()); logger.info("size : " + file.getSize()); logger.info("contentType : " +file.getContentType()); String savedName= uploadFile(file.getOriginalFilename(), file.getBytes()); model.addAttribute("savedName", savedName); } private String uploadFile(String originalName, byte[] fileData) throws Exception{ UUID uid=UUID.randomUUID(); String savedName=uid.toString() + "_"+ originalName; File target =new File(uploadPath, savedName); FileCopyUtils.copy(fileData, target); return savedName; } }
uploadForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form id="form1" action="uploadForm" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit"> </form> <script type="text/javascript"> var savedName = '${savedName}'; if (savedName != '') { alert(savedName); location.href = "/test/uploadForm"; } </script> </body> </html>
2. 기본적인 Ajax 방식의 파일 업로드
Controller
@Controller public class UploadController { private static final Logger logger = LoggerFactory.getLogger(UploadController.class); @Resource(name="uploadPath") private String uploadPath; //실질적으로 파일 저장 private String uploadFile(String originalName, byte[] fileData) throws Exception{ UUID uid=UUID.randomUUID(); String savedName=uid.toString() + "_"+ originalName; File target =new File(uploadPath, savedName); FileCopyUtils.copy(fileData, target); return savedName; } //Ajax 업로드용 컨트롤러와 JSP 작성하기 @RequestMapping(value="/test/uploadAjax", method=RequestMethod.GET) public void uploadAjax(){ } @ResponseBody @RequestMapping(value="/test/uploadAjax", method=RequestMethod.POST, produces="text/plain;charset=UTF-8") public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception{ logger.info("originalName , {} ", file.getOriginalFilename()); logger.info("size : " , file.getSize()); logger.info("contentType : " + file.getContentType()); return new ResponseEntity<String>(file.getOriginalFilename(), HttpStatus.CREATED); } }
uploadAjax.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <style type="text/css"> .fileDrop{ width:100%; height:200px; border:1px dotted blue; } small{ margin-left:3px; font-weight:bold; color:gray; } </style> </head> <body> <h3>Ajax File Upload</h3> <div class="fileDrop"></div> <div class="uploadedList"></div> <script src="//code.jquery.com/jquery-1.11.3.min.js"></script> <script> ~~ </script> </body> </html>
<script> $(".fileDrop").on("dragenter dragover", function(event){ event.preventDefault(); }); $(".fileDrop").on("drop", function(event){ event.preventDefault(); var files=event.originalEvent.dataTransfer.files; var file=files[0]; console.log(file); var formData=new FormData(); formData.append("file", file); $.ajax({ url:'/test/uploadAjax', data:formData, dataType:'text', processData:false, contentType:false, type:'POST', success:function(data){ alert(data); } }); }); </script>
drop 이벤트가 발생했을 때 이벤트 처리 코드의 핵심적인 부분은 dataTransfer.files 의 부분으로, 전달된 파일 데이터를 가져오는 부분이다.
event.originalEvent 는 jQuery 를 이용하는 경우 event 가 순수한 DOM 이벤가 아니기 때문에 event.originalEvent 를 이용해서 순수한 원래의
DOM 이벤트를 가져온다.
var file=files[0];
var formData=new FormData();
formData.append("file", file);
FormData append() 를 이용해서 file 이름으로 끌어다 놓은 파일 객체를 추가하는 것을 볼 수 있다.
FormData 의 경우 HTML5에서 지원되기 시작했기 때무에 브라우저의 제약이 있는 경우가 있다.
jquery의 $.ajax() 를 이용해서 FormData 객체에 있는 파일 데이터를 전송하기 위해서는 위 코드에 나와 있는 'processData' 와
'contentType' 옵션을 반드시 false 로 지정해야만 한다. 이 두개의 옵션은 데이터 전송을 <form> 태그를 이용하여 파일 업로드와 동일하게
해주는 결정적인 역할을 한다.
processData : 데이터를 일반적인 query string 으로 변환할 것인지를 결정한다. 기본값은 true, 'application/x-www-form-urlencoded' 타입으로
전송합니다. 다른 형식으로 데이터를 보내기 위하여 자동 변환하고 싶지 않은 경우는 false 를 지정합니다.
contentType : 기본 값은 'appplication / x-www-form-urlencoded' 이다. 파일의 경우 multipart/form-data 방식으로 전송하기 위해서 false 로
지정한다.
@RequestMapping(value="/test/uploadAjax", method=RequestMethod.POST,
produces="text/plain;charset=UTF-8")
@RequestMapping 의 속성으로 produces 속성을 지정하고 있는데, 이것은 한국어를 정상적으로 전송하기 위한 간단한 설정이다.
맨 마지막의 ResponseEntitiy 를 전송하는 부분에서는 HttpStatus.CREATED 값을 지정했다. HttpStatus.CREATED 는 원하는 리소스가
정상적으로 생성되었다는 상태 토드이다. 원한다면 HttpStatus.OK 를 이용해도 무방하다.
스프링 내 파일 경로를 가져 올때
package com.macaronics.www.util.fileupload; import java.io.File; import javax.servlet.http.HttpServletRequest; public class UploadPath { public static String attach_path ="WEB-INF/uploads/"; public static String path(HttpServletRequest request){ String uploadPath =""; try{ String root_path =request.getServletContext().getRealPath("/"); uploadPath =root_path+attach_path.replace('/', File.separatorChar); }catch(Exception e){ e.printStackTrace(); } return uploadPath; } }
댓글 ( 5)
댓글 남기기