(Spring) 12. 파일 업로드 구현

업데이트:
3 분 소요

File Upload 구현 (Spring)

1. 다중 파일 업로드

  • CommonsMultipartResolver 클래스를 이용하면 여러개 파일 한꺼번에 업로드 가능

2. 스프링 인터셉터 (intercepter)

  • 브라우저 요청 시 요청 메서드 호출 전후에 개발자가 원하는 기능을 수행함
  • 필터와 기능이 유사하지만 필터보다 좀더 자유롭게 위치를 변경해서 기능을 수행함
  • 쿠키 제어, 파일 업로드 등의 작업을 수행함

3. Test

1) pox.xml에 라이브러리 추가

<!-- 다중파일 업로드 -->
		<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.7</version>
		</dependency>

2) servlet - context 설정

  • CommonsMultipartResolver클래스를 사용하기위해서는 몇가지 설정이 더필요하다.
	<!-- MultipartResolver -->
	<beans:bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

		<!-- 최대로 업로드가 가능한 파일의 크기 설정 -->
		<beans:property name="maxUploadSize" value="50000000" />

		<!-- 디스크에 임시 파일을 생성하기 전 메모리 보관할수 있는 최대 바이트 크기 설정 -->
		<beans:property name="maxInMemorySize" value="1000000" />

		<!-- 전달되는 매개변수의 인코딩 -->
		<beans:property name="defaultEncoding" value="utf-8" />
	</beans:bean>

3) 입력받을 폼 생성

  • uploadForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%> <%@ taglib prefix="c"
uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />

<% request.setCharacterEncoding("UTF-8"); %>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>파일 업로드 하기</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script type="text/javascript">
      let cnt = 1;
      //파일추가 클릭하면 동적으로 파일 업로드를 추가함
      //name 속성값으로 file+cnt를 설정함으로서 값을 다르게 해줌
      function fnAddFile() {
        $("#d_file").append(
          "<br />" + "<input type='file' name='file" + cnt + "'/>"
        );
        cnt++;
      }
    </script>
  </head>
  <body>
    <h1>파일 업로드 하기</h1>
    <form
      action="${contextPath}/upload"
      method="post"
      enctype="multipart/form-data"
    >
      <label>아이디 : </label>
      <input type="text" name="id" /><br />
      <label>이름 : </label>
      <input type="text" name="name" /><br />
      <input type="button" value="파일 추가" onclick="fnAddFile()" /><br />

      <!-- 파일 추가 클릭하면 동적으로 파일 업로드를 추가함 -->
      <div id="d_file"></div>

      <input type="submit" value="업로드" />
    </form>
  </body>
</html>

alt

4) 입력받은 파일 처리할 컨트롤러 생성

  • FileUploadController.java를 생성해 따로생성한 폴더안에 입력받는다.
package kr.co.fileinter.fileupdown;

import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

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;

@Controller
public class FileUploadController {

	//파일 저장 위치 지정
	private static final String CURR_IMAGE_PEPO_PATH =
        "/Users/jeong-won-yeong/Documents/Spring/workspace-spring/imageRepo";

	@RequestMapping(value = "/form")
	public String form() {
		return "uploadForm";		//업로드창인 uploadForm.jsp를 반환함
	}

	@RequestMapping(value = "/upload" , method = RequestMethod.POST)
	public ModelAndView upload(MultipartHttpServletRequest multipartRequest,
                                            HttpServletResponse response)
			throws Exception {
		multipartRequest.setCharacterEncoding("utf-8");

		//매개변수 정보와 파일 정보를 저장할 Map을 생성함
		Map map = new HashMap();
		Enumeration enu = multipartRequest.getParameterNames();

		//전송된 매개변수 값을 key/value로 map에 저장함
		while(enu.hasMoreElements()) {
			String name = (String) enu.nextElement();
			String value = multipartRequest.getParameter(name);
			map.put(name, value);
		}


		//파일을 업로드한 후 반환된 파일이름이 저장된 fileList를 다시 map 저장함
		List<String> fileList = fileProcess(multipartRequest);
		map.put("fileList", fileList);

		//map을 결과창으로 포워딩함
		ModelAndView mav = new ModelAndView();
		mav.addObject("map", map);
		mav.setViewName("result");

		return mav;
	}

	//첨부한 파일 이름이 저장된 fileList 리턴함
	private List<String> fileProcess(MultipartHttpServletRequest multipartRequest)
                                                            throws Exception {
		List<String> fileList = new ArrayList<>();

		//첨부된 파일 이름 가져옴
		Iterator<String> fileNames = multipartRequest.getFileNames();
		while(fileNames.hasNext()) {
			String fileName = fileNames.next();
			//파일 이름에 대한 MultipartFile 객체를 가져옴
			MultipartFile mFile = multipartRequest.getFile(fileName);
			String originalFilename =  mFile.getOriginalFilename();			//실제 파일 이름 가져옴

			fileList.add(originalFilename);									//파일 이름을 하나씩 fileList에 저장

			File file = new File(CURR_IMAGE_PEPO_PATH +"\\"+ fileName);
			if(mFile.getSize() != 0) {										//첨부된 파일이 있는지 체크
				if(!file.exists()) {										//경로에 파일이 없으면 그 경로에 해당하는
					if(file.getParentFile().mkdirs()) {						//디렉토리를 만든 후 파일을 생성함
						file.createNewFile();
					}
				}
				//임시로 저장된 MultipartFile을  실제 파일로 전송
				mFile.transferTo(new File(CURR_IMAGE_PEPO_PATH +"\\"+ originalFilename));
			}
		}
		return fileList;			//첨부한 파일 이름이 저장된 fileList 반환함
	}

}
  • 다운로드 받은 파일을 화면에 뿌릴수 있는 컨트롤러 생성 (목적상)
  • FileDownloadController.java
package kr.co.fileinter.fileupdown;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class FileDownloadController {
	// 파일 저장 위치 지정
	private static final String CURR_IMAGE_PEPO_PATH = "/Users/jeong-won-yeong/Documents/Spring/workspace-spring/imageRepo";

	@RequestMapping("/download") // 다운로드할 이미지 파일 이름을 전달함
	public void download(@RequestParam("imageFileName") String imageFileName, HttpServletResponse response)
			throws Exception {

		OutputStream out = response.getOutputStream();

		String downFile = CURR_IMAGE_PEPO_PATH + "\\" + imageFileName;
		// 다운로드될 파일 객체 생성
		File file = new File(downFile);

		response.setHeader("Cache-Control", "no-cache");
		// 헤더에 파일이름 설정
		response.addHeader("Content-disposition", "attachment; fileName=" + imageFileName);

		FileInputStream in = new FileInputStream(file);
		byte[] buffer = new byte[1024 * 8]; // 버퍼를 이용해 한꺼번에 8kbyte씩 브라우저에 전송됨
		while (true) {
			int count = in.read(buffer);
			if (count == -1)
				break;
			out.write(buffer, 0, count);
		}
		in.close();
		out.close();
	}
}

5) 결과를 뿌릴 jsp 생성

  • result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>결과</title>
</head>
<body>
	<h1>업로드가 완료되었습니다.</h1>
	<label>아이디 : </label>
	<input type="text" name="id" value="${map.id }" readonly /><br/>
    <!-- map으로 넘어온 매개변수 값을 표시 -->
	<label>이름 : </label>
	<input type="text" name="name" value="${map.name }" readonly /><br/>
    <!-- map으로 넘어온 매개변수 값을 표시 -->

	<div>
		<!-- 업로드한 파일들 forEach문 이용해 img 태그에 표시함 -->
		<c:forEach var="imageFileName" items="${map.fileList }">
			<img alt="이미지" src="${contextPath}/download?imageFileName=${imageFileName}">
			<br/><br/><br/>
		</c:forEach>
	</div>
</body>
</html>

alt

댓글남기기