2017. 5. 1. 16:32ㆍJava/web
단일 파일 다운로드(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 형식 변환 규칙
- 아스키 문자(ASCII Code), '.', '-', '_' 등은 그대로 전달된다.
- 공백은 '+'로 전달된다.
- 기타 문자는 %ㅁㅁ와 같이 전달된다. 이때 %ㅁㅁ은 아스키 코드를 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]
'Java > web' 카테고리의 다른 글
[Spring] @RequestMapping의 produces 속성 (2) | 2017.07.22 |
---|---|
[Spring] AspectJ 적용 시 NoClassDefFoundError, ClassNotFoundException 발생 (2) | 2017.05.22 |
[모델2] Multipart를 이용한 단일 파일 업로드 구현하기 (게시판 구현) (0) | 2017.05.01 |
[Spring] MyBatis Mapper 파일 설정 방법 (0) | 2017.04.28 |
[Spring] JUnit 사용하기 (0) | 2017.04.26 |