toggle menu

JSP 정리 - 파일 업로드/다운로드 기능

2012. 8. 22. 17:14 JAVA/JSP

업로드
먼저 HTML의 폼 형태가 약간 달라지게 된다.
<form action="uploadPro.jsp" method="post" enctype="multipart/form-data">
	이름 : <input type="text" name="name"><br>
	파일 : <input type="file" name="file"><br>
	<input type="submit" name="업로드"><br>
</form>

이렇게 enctype을 설정하게되면, 이전과 같은 방식으로 파라메터를 받아올 수가 없다.
http://servlets.com/cos/  에서 받아 설치한 cos.lib 를 사용하면, MultipartRequest 를 사용할 수 있게 된다.

<%@page import="java.io.File"%>
<%@page import="com.oreilly.servlet.multipart.DefaultFileRenamePolicy"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title></title>
		<style></style>
		<script type="text/javascript"></script>
	</head>

	<body>
	
<%
	String saveDir = application.getRealPath("/ex0820/");
	int maxSize = 1024*1024*100;
	String encType = "UTF-8";

	MultipartRequest multipartRequest
	= new MultipartRequest(request, saveDir, maxSize, encType, new DefaultFileRenamePolicy());
	
    out.write("이름 : " + multipartRequest.getParameter("name") + "<br>");
    out.write("파일 : " + multipartRequest.getParameter("file") + "<br>"); //null 값을 갖는다.
    out.write("업로드파일명 : " + multipartRequest.getFilesystemName("file") + "<br>");
    out.write("원래파일명 : " + multipartRequest.getOriginalFileName("file") + "<br>");
    
    File file = multipartRequest.getFile("file");
%>

	<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
	파일용량 : <fmt:formatNumber value="<%=file.length() %>" groupingUsed="true"/>

	</body>
</html>

너무 편리하게 파일업로드 기능이 구현되었다.
업로드 이후의 과정은 파일입출력과 폼처리이므로 이전에 살펴본 내용들을 사용해서 처리하면 된다.



다운로드
파일을 다운로드하는 과정은 일반적으로 서블릿으로 처리한다.

① 업로드된 파일 경로 가져오기
② 한글 인코딩 설정
③ 요청된 파일이름을 File 객체로 변환
④ ContentType을 설정

response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=파일이름");


다운로드 링크에서 파일명을 인수로 넘겨준다.
request.getContextPath() + ... ? filename=파일명

그런데 인수명으로 넘겨줄 때 파일명이 깨질 수 있으므로 적절한 인코딩 과정을 거쳐 보내줄 필요가 있다.
파일들을 전체적으로 UTF-8 인코딩 상황에서 처리하고 있다면, 아래와 같이 인코딩 옵션에 "UTF-8" 로 잡아주어야 한다.


<%@page import="java.net.URLEncoder"%>
<%@page import="java.io.File"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title></title>
		<style></style>
		<script type="text/javascript"></script>
	</head>

	<body>
<%
	String saveDir = application.getRealPath("/ex0820/");
	File dir = new File(saveDir);
	
	String fName[] = dir.list();
	
	for(String fileName : fName )
	{
		out.write("<a href=\"" + request.getContextPath() + "/Download?filename=" + java.net.URLEncoder.encode(fileName, "UTF-8") + "\">" + fileName + "</a><br>");
	}
%>

	</body>
</html>



이제 실제로 다운로드를 구현하는 서블렛을 살펴보자.
텍스트 파일일 경우에도 다운로드 창이 뜰 수 있도록 설정해줄 필요가 있으며, 한글이나 특수문자 등의 인코딩에 주의해야한다.


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Download
 */
public class Download extends HttpServlet
{
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException
	{
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException
	{
		// ① 파일명 가져오기
		String fileName = request.getParameter("filename");
		
		// ② 경로 가져오기
		String saveDir = this.getServletContext().getRealPath("/ex0820/");
		File file = new File(saveDir + "/" + fileName);
		System.out.println("파일명 : " + fileName);
		
		
		// ③ MIMETYPE 설정하기
		String mimeType = getServletContext().getMimeType(file.toString());
		if(mimeType == null)
		{
			response.setContentType("application/octet-stream");
		}
		
		// ④ 다운로드용 파일명을 설정
		String downName = null;
		if(request.getHeader("user-agent").indexOf("MSIE") == -1)
		{
			downName = new String(fileName.getBytes("UTF-8"), "8859_1");
		}
		else
		{
			downName = new String(fileName.getBytes("EUC-KR"), "8859_1");
		}
		
		// ⑤ 무조건 다운로드하도록 설정
		response.setHeader("Content-Disposition","attachment;filename=\"" + downName + "\";");
		
		// ⑥ 요청된 파일을 읽어서 클라이언트쪽으로 저장한다.
		FileInputStream fileInputStream = new FileInputStream(file);
		ServletOutputStream servletOutputStream = response.getOutputStream();
		
		byte b [] = new byte[1024];
		int data = 0;
		
		while((data=(fileInputStream.read(b, 0, b.length))) != -1)
		{
			servletOutputStream.write(b, 0, data);
		}
		
		servletOutputStream.flush();
		servletOutputStream.close();
		fileInputStream.close();
	}
}












JAVA/JSP 관련 포스팅 더보기