공부방

File Upload&File Download 본문

스프링

File Upload&File Download

코딩 화이팅 2023. 4. 18. 16:35

 

id이름은 꼭 multipartResolver로 등록

CommonsMultipartResolver 속성

  • defalutEncoding(String) : 요청에서 사용할 기본 문자 인코딩 방식을 설정합니다.(UTF-8)
servlet-context.xml
<beans:property name="defaultEncoding" value="UTF-8"/>
  • maxUploadSize(long) : 업로드 가능 최대 크기(바이트)를 설정합니다.(-1은 무제한)
servlet-context.xml
<!-- 용량 작성 단위는 바이트 단위를 하겠다. -->
		<beans:property name="maxUploadSize" value="10485760"/>
<!-- 		 value="10485760"는 10메가 바이트 -->
  • maxinMemorySize(int) : 디스크에 쓰기 전에 메모리에 허용되는 최대 크기(바이트)를 설정합니다.
  • maxUploadSizePerFile(long) : 파일 당 최대 크기를 설정합니다.

파일 업로드 Form

servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />
	<resources  mapping="/upload/**" location="/upload/"></resources>
	

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.ssafy.mvc.controller" />
	
	<beans:bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" 
		id="multipartResolver">
		<beans:property name="defaultEncoding" value="UTF-8"/>
		<!-- 용량 작성 단위는 바이트 단위를 하겠다. -->
		<beans:property name="maxUploadSize" value="10485760"/> 
	</beans:bean>
	
	
	
</beans:beans>
======================================================================
MainController.java
package com.ssafy.mvc.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class MainController {
	//파일 업로드를 하기 위한 객체 생성
	@Autowired
	private ServletContext servletContext;


	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home() {
		return "home";
	}

	@GetMapping("regist")
	public String registForm() {
		return "regist";
	}
	
	@PostMapping("upload")
	public String upload(MultipartFile upload_file, Model model) {
		// 실제 저장될 위치 가져와
		String uploadPath = servletContext.getRealPath("/upload");
		// 만약에 등록하려고 하는 upload 폴더가 없을 수도 있다.
		File folder = new File(uploadPath);
		
		if (!folder.exists())
			folder.mkdir(); // 폴더 없으면 만들어

		// 실제 파일이름 가져와
		String fileName = upload_file.getOriginalFilename();
		File target = new File(uploadPath, fileName);

		// 파일을 해당 폴더에 저장을 하자.
		// 저장방법은 크게 2가지
		// 1.FileCopyUtiles
		// 2.File인스턴스를 이용

		try {
			FileCopyUtils.copy(upload_file.getBytes(), target);
		} catch (IOException e) {
			e.printStackTrace();
		}

		model.addAttribute("fileName", fileName);
		return "result";
	}
}
======================================================================
home.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>
	<a href="regist">파일등록하러가자</a>
</body>
</html>
======================================================================
regist.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파일업로드</title>
</head>
<body>
	<h2>파일 업로드</h2>
	<form action="upload" method="POST" enctype="multipart/form-data">
		<input type="file" name="upload_file">
		<input type="submit" value="파일등록">
	</form>
</body>
</html>
======================================================================
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	
		${fileName} <br>

</body>
</html>

파일 등록을 누르면

경로를 누르면 사진을 볼 수 있게 해주기

servlet-context.xml
<resources  mapping="/upload/**" location="/upload/"></resources>
=================================================================
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	<a href="/mvc/upload/${fileName}">${fileName}</a>
	
</body>
</html>

 

저걸 누르면

바로 사진을 나오게 하기

나머지는 위의 코드와 동일
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	<a href="/mvc/upload/${fileName}">${fileName}</a>
	<!-- 컨택스트 루트를 직접 적는건 굉장히 별로.... -->
	<img src="${pageContext.request.contextPath}/upload/${fileName}"/>
</body>
</html>

다운로드 받기

나머지 코드는 위와 동일
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	<a href="/mvc/upload/${fileName}">${fileName}</a>
	<!-- 컨택스트 루트를 직접 적는건 굉장히 별로.... -->
	<img src="${pageContext.request.contextPath}/upload/${fileName}"/>
	<a href="download?fileName=${fileName}">${fileName}다운로드</a>
</body>
</html>

다운로드를 누르면

아직 다운로드를 했을 때 해준게 없어 오류가 난다.

servlet-context.xml
<beans:bean class="com.ssafy.mvc.view.FileDownLoadView" id="fileDownLoadView"/>
	<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
		<beans:property name="order" value="0"></beans:property>
	</beans:bean>
===============================================================
MainController.java 
package com.ssafy.mvc.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class MainController {
	//파일 업로드를 하기 위한 객체 생성
	@Autowired
	private ServletContext servletContext;


	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home() {
		return "home";
	}

	@GetMapping("regist")
	public String registForm() {
		return "regist";
	}
	
	@PostMapping("upload")
	public String upload(MultipartFile upload_file, Model model) {
		// 실제 저장될 위치 가져와
		String uploadPath = servletContext.getRealPath("/upload");
		// 만약에 등록하려고 하는 upload 폴더가 없을 수도 있다.
		File folder = new File(uploadPath);
		
		if (!folder.exists())
			folder.mkdir(); // 폴더 없으면 만들어

		// 실제 파일이름 가져와
		String fileName = upload_file.getOriginalFilename();
		File target = new File(uploadPath, fileName);

		// 파일을 해당 폴더에 저장을 하자.
		// 저장방법은 크게 2가지
		// 1.FileCopyUtiles
		// 2.File인스턴스를 이용

		try {
			FileCopyUtils.copy(upload_file.getBytes(), target);
		} catch (IOException e) {
			e.printStackTrace();
		}

		model.addAttribute("fileName", fileName);
		return "result";
	}
	
	@GetMapping("download")
	public String download(Model model, String fileName) {
		Map<String, Object> fileInfo = new HashMap<>();

		fileInfo.put("fileName", fileName);

		// 폴더 구조이름
		// 원래 파일 이름
		// 지금 파일 이름 .... 등등을 잔뜩 넣어서 downLoadView에서 컨츄롤을 해라

		model.addAttribute("downloadFile", fileInfo);

		return "fileDownLoadView";
	}
}
===============================================================
FileDownLoadView.java
package com.ssafy.mvc.view;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class FileDownLoadView extends AbstractView {

	public FileDownLoadView() {
		setContentType("application/download; charset=UTF-8");
	}
	
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		//////////////////////////////////////////////////////////////////////
		ServletContext ctx = getServletContext();
		String realPath = ctx.getRealPath("/upload");
		
		//우리가 다운로드 받을 파일의 경로가 다르면 위의 코드도 달라져야 함.
		
		Map<String, Object> fileInfo = (Map<String, Object>) model.get("downloadFile"); // 전송받은 모델(파일 정보)
        String fileName = (String) fileInfo.get("fileName");    // 파일 경로
        
        System.out.println(fileName);
        File file = new File(realPath, fileName);
		/////////////////////////////////////////////////////////////////////
        
        response.setContentType(getContentType());
        response.setContentLength((int) file.length());
        
        String header = request.getHeader("User-Agent");
        boolean isIE = header.indexOf("MSIE") > -1 || header.indexOf("Trident") > -1;
        String filename = null;
        // IE는 다르게 처리
        if (isIE) {
        	filename = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        } else {
            filename = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
        response.setHeader("Content-Transfer-Encoding", "binary");
        
        OutputStream out = response.getOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            FileCopyUtils.copy(fis, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try { 
                    fis.close(); 
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        out.flush();
    }
}
===============================================================
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	<a href="/mvc/upload/${fileName}">${fileName}</a>
	<!-- 컨택스트 루트를 직접 적는건 굉장히 별로.... -->
	<img src="${pageContext.request.contextPath}/upload/${fileName}"/>
	<a href="download?fileName=${fileName}">${fileName}다운로드</a>
</body>
</html>

파일을 넣고 다운로드를 누르면 이제 다운로드가 된다.

여러 파일을 넣는 경우

나머지 코드는 위와 동일
result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>파일업로드</title>
</head>
<body>
	<h2>파일 업로드</h2>
	<form action="upload" method="POST" enctype="multipart/form-data">
		<input type="file" name="upload_file">
		<input type="submit" value="파일등록">
	</form>
	<!-- 여러개의 파일을 동시에 올려보자!!! -->
	<form action="upload2" method="POST" enctype="multipart/form-data">
		<input type="file" name="upload_files" multiple="multiple">
		<input type="submit" value="파일등록">
	</form>
</body>
</html>

위는 아까 만들었던 것이라 하나밖에 선택이 안되고 밑에꺼는 중복 선택이 가능하다.

나머지 코드는 위와 동일
MainController.java
package com.ssafy.mvc.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class MainController {
	//파일 업로드를 하기 위한 객체 생성
	@Autowired
	private ServletContext servletContext;
	// resource 경로를 가져오기 위해서 사용한다.
	@Autowired
	private ResourceLoader resLoader;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home() {
		return "home";
	}

	@GetMapping("regist")
	public String registForm() {
		return "regist";
	}
	
	@PostMapping("upload")
	public String upload(MultipartFile upload_file, Model model) {
		// 실제 저장될 위치 가져와
		String uploadPath = servletContext.getRealPath("/upload");
		// 만약에 등록하려고 하는 upload 폴더가 없을 수도 있다.
		File folder = new File(uploadPath);
		
		if (!folder.exists())
			folder.mkdir(); // 폴더 없으면 만들어

		// 실제 파일이름 가져와
		String fileName = upload_file.getOriginalFilename();
		File target = new File(uploadPath, fileName);

		// 파일을 해당 폴더에 저장을 하자.
		// 저장방법은 크게 2가지
		// 1.FileCopyUtiles
		// 2.File인스턴스를 이용

		try {
			FileCopyUtils.copy(upload_file.getBytes(), target);
		} catch (IOException e) {
			e.printStackTrace();
		}

		model.addAttribute("fileName", fileName);
		return "result";
	}
	
	@GetMapping("download")
	public String download(Model model, String fileName) {
		Map<String, Object> fileInfo = new HashMap<>();

		fileInfo.put("fileName", fileName);

		// 폴더 구조이름
		// 원래 파일 이름
		// 지금 파일 이름 .... 등등을 잔뜩 넣어서 downLoadView에서 컨츄롤을 해라

		model.addAttribute("downloadFile", fileInfo);

		return "fileDownLoadView";
	}
	
	@PostMapping("upload2")
	public String upload2(MultipartFile[] upload_files, Model model) throws IOException {

		// 파일들의 이름을 저장할 리스트를 생성하자 (임시)
		List<String> list = new ArrayList<>();

		// 널이 아니면 이렇게 사전에 작업을 해주는게 사실 조금더 안전함.
		if (upload_files != null) {
			Resource res = resLoader.getResource("resources/upload");
			if (!res.getFile().exists())
				res.getFile().mkdir();

			// 지금은 단순히 upload라고 하는 폴더에 파일을 그대로 저장하고 있다.
			// 폴더 구조 2023/04/18 구조를 잡고 저장하는 것이 조금더 있어보인다.
			// 파일 이름도 실제로 저장할 때는 OriginName / 저장할 이름 두가지로 나누어서 저장을 하는것도 하나의 바업ㅂ이다.
			// 같은 이름을 사용하면 덮어버리기 때문에...

			for (MultipartFile mfile : upload_files) {
				// 조금 더 커팅해보면
				if (mfile.getSize() > 0) { // 파일이 있으면...
					mfile.transferTo(new File(res.getFile(), mfile.getOriginalFilename()));
					list.add(mfile.getOriginalFilename());
				}
			}
		}

		model.addAttribute("list", list);

		return "result";
	}
}
==================================================================
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" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
	<a href="/mvc/upload/${fileName}">${fileName}</a>
	<!-- 컨택스트 루트를 직접 적는건 굉장히 별로.... -->
	<img src="${pageContext.request.contextPath}/upload/${fileName}"/>
	<a href="download?fileName=${fileName}">${fileName}다운로드</a>
	<c:forEach items="${list}" var="fileName">
		${fileName} <br>
	</c:forEach>
</body>
</html>

 

'스프링' 카테고리의 다른 글

MyBatis-Spring  (0) 2023.04.20
MyBatis  (0) 2023.04.19
Interceptor  (0) 2023.04.17
Spring Web MVC  (0) 2023.04.13
Spring AOP  (0) 2023.04.12