목차

File Upload 서비스

개요

업로드는 한 컴퓨터 시스템에서 다른 시스템으로 파일을 전송하는 것을 말하는데, 대개 작은 컴퓨터에서 큰 컴퓨터로 옮길 때 이런 용어를 사용한다. 네트웍 사용자의 관점에서 보면, 파일을 업로드하는 것은 그 파일을 받을 수 있도록 설정된 다른 컴퓨터에 파일을 보내는 것이다. 전자게시판 상의 다른 사용자와 이미지 파일을 공유하기를 원하는 사람들은 그 전자게시판에 파일을 업로드하면 된다.

그러면 반대편 입장에 있는 사람은 그 파일을 다운로드하게 되는데, 여기서 다운로드는 대개 큰 컴퓨터에서 작은 컴퓨터로 파일을 전송하는 것을 의미한다. 인터넷 사용자의 입장에서의 다운로드란 다른 컴퓨터에서 파일을 받는 것이다.

설명

파일 업로드 기능을 구현하기 위해서는 먼저 빈 설정 파일에 다음과 같이 MultiCommonsMultipartResolver를 정의해야한다. 본 가이드에서는 Apache Commens FileUpload에서 재공하는 CommonsMultipartResolver를 사용하기를 권장한다. CommonsMultipartResolver를 수정하여 사용할 경우 많은 부분에 시간과 노력이 들어갈 것이다.

	<!-- Custom MultiFile resolver -->
<bean id="local.MultiCommonsMultipartResolver"
	class="egovframework.rte.util.web.resolver.MultiCommonsMultipartResolver">
	<property name="maxUploadSize" value="100000000" />
	<property name="maxInMemorySize" value="100000000" />
</bean>

[권장]만약 스프링에서 제공하는 Apache Commens FileUpload API를 이용하여 파일 업로드를 처리하는 CommonsMultipartResolver를 사용하려고 하면 빈 설정파일에 다음과 같이 정의한다.

<!-- MULTIPART RESOLVERS -->
<!-- regular spring resolver -->
<bean id="spring.RegularCommonsMultipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="100000000" />
	<property name="maxInMemorySize" value="100000000" />
</bean>

또한 해당 컨트롤러의 property로 파일의 업로드 위치를 지정해주고 컨트롤러에서 setter 메소드를 통해 지정된 파일 업로드 위치를 불러올 수 있다. 사용예는 다음과 같다.

fileUploadProperties.properties

# windows NT일 경우  
file.upload.path=C:\\temp
 
# Unix일 경우
file.upload.path=/usr/file/upload
@Resource(name = "fileUploadProperties")
Properties fileUploadProperties;
..
..
..
	String uploadPath = fileUploadProperties
			.getProperty("file.upload.path");
	File saveFolder = new File(uploadPath);
..
..
..

파일 업로드를 위해 JSP파일의 입력 폼 타입을 file로 지정하고 form의 enctype을 multipart/form-data로 지정한다. 예시는 다음과 같다. 이때 CommonsMultipartResolver를 사용할 경우 form의 name을 다르게 설정하여야 한다. 중복된 이름을 사용할 경우 에러가 발생한다.

<form method="post" action="<c:url value='/upload/genericMulti.do'/>"
enctype="multipart/form-data">
  <p>Type:
    <input type="text" name="type" value="genericFileMulti" size="60" />
  </p>
  <p>File1:
    <input type="file" name="file[]" size="60" />
  </p>
  <p>File2:
    <input type="file" name="file[]" size="60" />
  </p>
  <p>
    <input type="submit" value="Upload" />
  </p>
</form>

다음은 파일 업로드를 위해 Controller를 구현한 모습이다.

@Controller("genericFileUploadController")
public class GenericFileUploadController {
 
@Resource(name = "multipartResolver")
CommonsMultipartResolver multipartResolver;
 
@Resource(name = "fileUploadProperties")
Properties fileUploadProperties;
 
@SuppressWarnings("unchecked")
@RequestMapping(value = "/upload/genericMulti.do")
public String multipartProcess(final HttpServletRequest request, Model model)
	throws Exception {
 
final long startTime = System.nanoTime();
 
/*
 * validate request type
 */
Assert.state(request instanceof MultipartHttpServletRequest,
		"request !instanceof MultipartHttpServletRequest");
final MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
 
/*
 * validate text input
 */
Assert.state(request.getParameter("type").equals("genericFileMulti"),
		"type != genericFileMulti");
 
/*
 * extract files
 */
final Map<String, MultipartFile> files = multiRequest.getFileMap();
Assert.notNull(files, "files is null");
Assert.state(files.size() > 0, "0 files exist");
 
/*
 * process files
 */
String uploadPath = fileUploadProperties
		.getProperty("file.upload.path");
File saveFolder = new File(uploadPath);
 
// 디렉토리 생성
if (!saveFolder.exists() || saveFolder.isFile()) {
	saveFolder.mkdirs();
}
 
Iterator<Entry<String, MultipartFile>> itr = files.entrySet()
		.iterator();
MultipartFile file;
List fileInfoList = new ArrayList();
String filePath;
 
while (itr.hasNext()) {
	Entry<String, MultipartFile> entry = itr.next();
	System.out.println("[" + entry.getKey() + "]");
 
	file = entry.getValue();
	if (!"".equals(file.getOriginalFilename())) {
		filePath = uploadPath + "\\" + file.getOriginalFilename();
		file.transferTo(new File(filePath));
 
		FileInfoVO fileInfoVO = new FileInfoVO();
		fileInfoVO.setFilePath(filePath);
		fileInfoVO.setFileName(file.getOriginalFilename());
		fileInfoVO.setFileSize(file.getSize());
		fileInfoList.add(fileInfoVO);
	}
}
 
// 여기서는 DB에 파일관련 정보를 저장하지 않고 단순히 success 페이지로 포워딩 하여 재확인 가능토록 함
model.addAttribute("fileInfoList", fileInfoList);
model.addAttribute("uploadPath", uploadPath);
 
final long estimatedTime = System.nanoTime() - startTime;
System.out.println(estimatedTime + " " + getClass().getSimpleName());
 
return "success";
 
	}
}

Tomcat에서는 일반적으로 웹 어플리케이션이 GET과 POST 방식으로 파라미터를 넘겨 받을 때 request.setCharacterEncoding()을 통한 문자셋 인코딩이 필요하다.

참고 자료