JAVA-WEB January 04, 2021

JSP-05 File Upload Download

Words count 7.6k Reading time 7 mins.

File upload

  1. cos.jar 라이브러리를 추가한다. (servlets.com)

    1. MultipartRequest 클래스를 이용한다.
    2. 기존의 request를 이용해서 MultipartRequest 클래스 객체를 만든다.
  2. <form method="post"enctype="multipart/form-data">

  3. <input type="file" name="" />

  4. 업로드 할 디렉토리(폴더)를 생성해 둔다.
    -> WebContent 디렉토리 아래에 임의의 디렉토리를 만든다.


업로드 페이지

uploadPage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <h3>파일 업로드 폼</h3>
    <form action="upload.jsp"
          method="post"
          enctype="multipart/form-data">

          업로더 <input type="text" name="uploader" /><br/><br/>
          첨부 <input type="file" name="filename" /><br/><br/>
          <button>올리기</button>

    </form>

</body>
</html>

업로드 설정

upload.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%-- 업로드가 진행되는 곳 --%>
<%
    // request의 인코딩을 할 필요가 없다.
    // MultipartRequest 객체를 만들 때 인코딩을 한다.

    // 디렉토리명을 변수로 저장한다.
    String directory = "archive";
    // 디렉토리의 실제 경로를 알아낸다.
    String realPath = request.getServletContext().getRealPath(directory);

    // MultipartRequest 객체를 만든다. (이 때 업로드가 진행된다.)
    MultipartRequest multipart = new MultipartRequest(
            request,
            realPath,
            1024 * 1024 * 10,  // 업로드 크기 (10MB)
            "UTF-8",
            new DefaultFileRenamePolicy()  // 동일한 파일이 업로드되면 기존 파일명을 수정하는 방법이다.(원래 파일명에 숫자 붙이기)
            );
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <h3>업로드 결과</h3>
    <ul>
        <li>경로: <%=realPath%></li>
        <li>업로더: <%=request.getParameter("uploader")%></li>
        <li>업로더: <%=multipart.getParameter("uploader")%></li>
        <li>올릴 때 파일명: <%=multipart.getOriginalFileName("filename")%></li>
        <li>저장된 파일명: <%=multipart.getFilesystemName("filename")%></li>
        <%
            // multipart 객체에 저장된 파일을 가져오는 메소드: getFile()
            File file = multipart.getFile("filename");
            // file을 통해서 필요한 정보를 얻어낸다.
            String filename = file.getName();        // 파일명
            long filesize = file.length() / 1024;    // file.length()는 바이트이므로 / 1024를 통해서 KB로 변환
            pageContext.setAttribute("filesize", filesize);
            String lastModifiedDate = new SimpleDateFormat("yyyy-MM-dd a h:mm").format(file.lastModified());  // 최종 수정일
        %>
        <li>저장된 파일명: <%=filename%></li>
        <li>파일크기: <fmt:formatNumber value="${filesize}" pattern="#,##0" />KB</li>
        <li>최종수정일: <%=lastModifiedDate%></li>
    </ul>

    <br/><br/>

    <a href="download.jsp?directory=<%=directory%>&filename=<%=filename%>">다운로드</a>

</body>
</html>

다운로드 설정

download.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    request.setCharacterEncoding("UTF-8");
    String directory = request.getParameter("directory");
    String filename = request.getParameter("filename");

    // 1. realPath 알아내기
    String realPath = request.getServletContext().getRealPath(directory);

    // 2. filename을 이용해서 File 객체 생성하기
    // File file = new File(realPath, filename);   // new File(realPath + "/" + filename);
    File file = new File(realPath, filename);
    // 3. (이건 다운로드다)라는 헤더 타입을 만든다.
    // 파일의 이름과 파일의 길이가 필요하다.
    // 서버 -> 사용자 : response의 헤더 작업
    // response.setContentType("application/x-msdownload");  // 아래와 같은 코드입니다.
    response.setHeader("Content-Type", "application/x-msdownload");
    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", " "));
    // response.setContentLengthLong(file.length());  // 아래와 같은 코드입니다.
    response.setHeader("Content-Length", file.length() + "");

    // 4. 진짜 다운로드를 진행한다. (파일복사와 유사한 프로그램)
    // 모든 파일을 처리할 수 있는 바이트 기반 스트림을 사용한다.
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {

        // JSP에서 OutputStream을 사용하려면 
        // JSP와 Servlet의 출력스트림 겹침 방지(IllegalStateException 발생 방지)처리가 필요하다.
        out.clear();
        out = pageContext.pushBody();

        bis = new BufferedInputStream(new FileInputStream(file));
        bos = new BufferedOutputStream(response.getOutputStream());

        // 한 번에 옮기기
        // file.length() 만큼 byte 배열을 확보해서 옮긴다.
        byte[] array = new byte[(int)file.length()];

        // 서버에서 읽기
        bis.read(array, 0, (int)file.length());
        // 읽은 내용을 array배열의 0번인덱스부터 길이만큼 영역에 저장해라.
        // (int)file.length() -> 길이가 10이라면
        // bis.read(array, 0, 10) : array배열의 0번인덱스부터 10개공간 사용해서 저장해라.

        // 사용자에게 쓰기
        bos.write(array);

    } catch (FileNotFoundException e) {

    } catch (IOException e) {

    } finally {
        try {
            if (bos != null) {
                bos.close();
            }
            if (bis != null) {
                bis.close();
            }
        } catch (Exception e) {

        }
    }

%>

업로드 페이지및 결과 페이지

처음화면

업로드 파일 선택 후 화면

올린 후 화면

다운로드

밑의 다운로드를 누르면 다운로드가 동작합니다.

0%