업로드
먼저 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(); } }