티스토리 뷰

저번 포스팅에서 multipart/form-data를 form 태그에 사용하여 DB에 파일을 저장하는 방법을 이야기했었다면, 이번 포스팅에서는 DB에 저장된 파일 이름과 경로를 가지고 사용자가 <a> 태그를 클릭했을 때, 해당 파일을 다운로드할 수 있게끔 해주는 방법을 작성해보도록 하겠다.


우선 DB는 file객체의 이름과 절대 경로를 가지고 있고, 첨부파일을 가지고 있는 페이지로 넘어오는 과정에서 controller가 이미 fileName과 경로를 response했다고 가정한다. (파일의 절대 경로는 어차피 사용하지 않지만, 혹시 몰라서...)

다음으로 파일의 경로는 프로젝트의 WebContent/files 내에 있다.

 

우선 다음과 같이 <a> 태그를 작성했다.

첨부파일: <a href = "file_download.do?fileName=${requestScope.dto.getFileName() }">${requestScope.dto.getFileName() }</a>

 

다음으로 해당 파일의 이름을 파라미터로 받는 컨트롤러는 다음과 같이 작성하여 사용자가 파일을 다운로드할 수 있게 한다.

 

◎file_download.do

package com.choonham.mpd.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/file_download.do")
public class FileDownload extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		 // 파일 업로드된 경로
	    String root = request.getSession().getServletContext().getRealPath("/");
	    String savePath = root + "files";
	    
	    // 서버에 실제 저장된 파일명
	    String filename = request.getParameter("fileName");
	     
	    // 실제 내보낼 파일명
	    String orgfilename = request.getParameter("fileName");
	      
	 
	    InputStream in = null;
	    OutputStream os = null;
	    File file = null;
	    boolean skip = false;
	    String client = "";

	    try{
	        // 파일을 읽어 스트림에 담기
	        try{
	            file = new File(savePath, filename);
	            in = new FileInputStream(file);
	        }catch(FileNotFoundException fe){
	            skip = true;
	        }

	        client = request.getHeader("User-Agent");
	 
	        // 파일 다운로드 헤더 지정
	        response.reset() ;
	        response.setContentType("application/octet-stream");
	        response.setHeader("Content-Description", "JSP Generated Data");
	 
	 
	        if(!skip){
	 
	             
	            // IE
	            if(client.indexOf("MSIE") != -1){
	                response.setHeader ("Content-Disposition", "attachment; filename="+new String(orgfilename.getBytes("KSC5601"),"ISO8859_1"));
	 
	            }else{
	                // 한글 파일명 처리
	                orgfilename = new String(orgfilename.getBytes("utf-8"),"iso-8859-1");
	 
	                response.setHeader("Content-Disposition", "attachment; filename=\"" + orgfilename + "\"");
	                response.setHeader("Content-Type", "application/octet-stream; charset=utf-8");
	            } 
	             
	            response.setHeader ("Content-Length", ""+file.length() );

	            os = response.getOutputStream();
	            byte b[] = new byte[(int)file.length()];
	            int leng = 0;
	             
	            while( (leng = in.read(b)) > 0 ){
	                os.write(b,0,leng);
	            }
	 
	        }else{
	            response.setContentType("text/html;charset=UTF-8");
	            PrintWriter out = response.getWriter();
	            out.println("<script language='javascript'>alert('파일을 찾을 수 없습니다');history.back();</script>");
	        }
	         
	        in.close();
	        os.close();
	 
	    }catch(Exception e){
	      e.printStackTrace();
	    }
	}


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

	}

}

 

생각보다 복잡해서, 처음 구글링을 할 때는 꽤나 당황했는데, 막상 작성해보면 인코딩해주는 부분과 헤더를 작성해주는 것이 생소할 뿐, 간단한 코드이다.

 

반응형
Comments