Bigfat

[모델2] 단일 파일 다운로드 구현하기 (게시판 구현) 본문

Java/web

[모델2] 단일 파일 다운로드 구현하기 (게시판 구현)

kyou 2017. 5. 1. 16:32

단일 파일 다운로드(Single File Download)를 구현해보자

  WebContent/bbs.properties에 /download.bbs 요청과 요청을 처리할 DownloadImpl 클래스를 매핑해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#bbs.properties
/writeForm.bbs=com.edu.bbs.WriteFormImpl
/write.bbs=com.edu.bbs.WriteImpl
/list.bbs=com.edu.bbs.ListImpl
/content.bbs=com.edu.bbs.ContentImpl
/login.bbs=com.edu.bbs.LoginImpl
/logout.bbs=com.edu.bbs.LogoutImpl
/updateForm.bbs=com.edu.bbs.UpdateFormImpl
/update.bbs=com.edu.bbs.UpdateImpl
/delete.bbs=com.edu.bbs.DeleteImpl
/replyForm.bbs=com.edu.bbs.ReplyFormImpl
/reply.bbs=com.edu.bbs.ReplyImpl
/commentWrite.bbs=com.edu.comment.CommentWriteImpl
/commentRead.bbs=com.edu.comment.CommentReadImpl
/download.bbs=com.edu.bbs.DownloadImpl
cs


  다운로드 링크를 삽입할 자리에 아래 코드를 작성한다.

1
<a href="/bbs/download.bbs?fileName=${article.fileName}">${article.fileName}</a>
cs


  요청을 처리할 DownloadImpl 클래스를 아래와 같이 작성한다.

  업로드는 Request Hearder에서 데이터에 대한 정보를 가져오고, 다운로드는 Response Header에 정보를 작성해줘야 한다. URLEncoder.encode 메서드를 이용해 파일명을 UTF-8로 인코딩한다. 운영체제마다 일부 문자를 인식하는 방법이 다르기 때문에 이러한 인코딩 과정이 필요하다. URLEncoder 클래스는 데이터를 웹서버에서 요구하는 데이터 형식인 x-www-form-urlencoded라고 불리는 MIME 형식으로 바꾸는 기능을 한다(참고1).


  - MIME 형식 변환 규칙

  1. 아스키 문자(ASCII Code), '.', '-', '_' 등은 그대로 전달된다.
  2. 공백은 '+'로 전달된다.
  3. 기타 문자는 %ㅁㅁ와 같이 전달된다. 이때 %ㅁㅁ은 아스키 코드를 16진수화한 결과를 나타낸 것이다.

  UTF-8 인코딩은 유니코드 한 문자를 나타내기 위해 1바이트에서 4바이트까지를 사용하며, U+0000부터 U+007F(00007F) 범위에 있는 ASCII 문자들은 UTF-8에서 1바이트만으로 표시된다(참고2). 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.edu.bbs;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class DownloadImpl implements BBSService {
 
    @Override
    public String bbsService(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String saveDirectory = req.getServletContext().getInitParameter("saveDirectory");
        String filename = req.getParameter("fileName");
        
        File file = new File(saveDirectory + filename);
        
//        resp.setContentType("aplication/octet-stream");        // download 동일
        resp.setContentType("aplication/download");
//        resp.setContentLength((int) file.length());
        resp.setContentLengthLong(file.length());
        
        // 모든 브라우저가 지원
        filename = URLEncoder.encode(filename, "utf-8").replace("+""%20").replace("(""%28").replace(")""%29");
        
        // 익스플로러는 지원 안됨
//        originFileName = new String(originFileName.getBytes("utf-8"), "iso-8859-1").replace("+", "%20");
 
        // Content-Disposition: form-data; name="fileName"; filename="파일명"
        resp.setHeader("Content-Disposition""attachment; filename=\"" + filename + "\";");
        
        OutputStream out = resp.getOutputStream();
        FileInputStream fis = null;
        
        try {
            int temp;
            fis = new FileInputStream(file);
            while((temp = fis.read()) != -1) {
                out.write(temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
        
        return null;
    }
 
}
cs


  아래는 업로드한 파일을 다운로드했을 때, DownloadImpl 클래스에서 Response setter 메서드로 작성한 Content-Type, Content-Length, Content-Disposition를 Response Header에서 확인할 수 있다.


  복수 파일 다운로드는 해당 게시글(article_number)에 대한 업로드한 파일들의 정보를 알 수 있다면, JSP에서 JSTL의 foreach을 이용해 쉽게 구현할 수 있다. 하지만 파일 정보에 대한 새로운 테이블과 기존 게시판 테이블의 수정이 필요하므로 이는 스프링 프로젝트에서 진행하고자 한다.



[자바 네트워크 프로그래밍 URLEncoder, URLDecoder, URLConnection 클래스 참고1]

[UTF-8, Wikipedia 참고2]