Spring

[FileUpload] 파일 다운로드

sujin7837 2022. 4. 22. 17:03
반응형

File Download

servlet-context.xml 파일 설정

<!-- fileDownload -->
<beans:bean id="fileDownLoadView" class="com.ssafy.guestbook.view.FileDownLoadView"/>
<beans:bean id="fileViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <beans:property name="order" value="0" />
</beans:bean>

 

jsp 파일 작성

 <script type="text/javascript">
    $(document).ready(function () {
        //file download
        $('.filedown').click(function() {
            alert("원본 :  " + $(this).attr('ofile') + "      실제 :  " + $(this).attr('sfile'));
            $(document).find('[name="sfolder"]').val($(this).attr('sfolder'));
            $(document).find('[name="ofile"]').val($(this).attr('ofile'));
            $(document).find('[name="sfile"]').val($(this).attr('sfile'));
            $('#downform').attr('action', '${root}/guestbook/download').attr('method', 'get').submit();
        });
    });
</script>

<form id="downform">
    <input type="hidden" name="sfolder">
    <input type="hidden" name="ofile">
    <input type="hidden" name="sfile">
</form>

<ul>
    <c:forEach var="file" items="${article.fileInfos}">
        <li>${file.originFile} <a href="#" class="filedown" sfolder="${file.saveFolder}" sfile="${file.saveFile}" ofile="${file.originFile}">[다운로드]</a>
    </c:forEach>
</ul>

 

자바 클래스에서 다운로드 메서드 작성

@GetMapping(value = "/download")
public ModelAndView downloadFile(@RequestParam("sfolder") String sfolder, @RequestParam("ofile") String ofile,
        @RequestParam("sfile") String sfile, HttpSession session) {
    MemberDto memberDto = (MemberDto) session.getAttribute("userinfo");
    if (memberDto != null) {
        Map<String, Object> fileInfo = new HashMap<String, Object>();
        fileInfo.put("sfolder", sfolder);
        fileInfo.put("ofile", ofile);
        fileInfo.put("sfile", sfile);

        return new ModelAndView("fileDownLoadView", "downloadFile", fileInfo);
    } else {
        return new ModelAndView("redirect:/");
    }
}

ModelAndView에서 첫번째 인자는 view name이 들어갑니다. 그러면 '/WEB-INF/views/fileDownLoadView.jsp'라는 경로로 이동하게 되는데, 파일 다운로드를 수행하려는데 jsp 파일로 이동하는 것은 목적에 적합하지 않은 수행입니다. 앞서 servlet-context.xml 파일 설정에서 파일 다운로드 관련 빈을 설정해주었는데, 이것은 위에서 언급한 jsp 파일 경로로 이동하지 않고 fileDownLoadView라는 이름의 자바 클래스로 이동하게 합니다. 아래는 fileDownLoadView 클래스를 작성한 것으로, 파일 다운로드를 처리해줍니다.

 

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class FileDownLoadView extends AbstractView {

	public FileDownLoadView() {
		setContentType("apllication/download; charset=UTF-8");
	}
	
	@Override
	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		ServletContext ctx = getServletContext();
		String realPath = ctx.getRealPath("/upload");
		
		Map<String, Object> fileInfo = (Map<String, Object>) model.get("downloadFile"); // 전송받은 모델(파일 정보)
        
        String saveFolder = (String) fileInfo.get("sfolder");    // 파일 경로
        String originalFile = (String) fileInfo.get("ofile");    // 원본 파일명(화면에 표시될 파일 이름)
        String saveFile = (String) fileInfo.get("sfile");    // 암호화된 파일명(실제 저장된 파일 이름)
        File file = new File(realPath + File.separator  + saveFolder, saveFile);
		
        response.setContentType(getContentType());
        response.setContentLength((int) file.length());
        
        String header = request.getHeader("User-Agent");
        boolean isIE = header.indexOf("MSIE") > -1 || header.indexOf("Trident") > -1;
        String fileName = null;
        // IE는 다르게 처리
        if (isIE) {
        	fileName = URLEncoder.encode(originalFile, "UTF-8").replaceAll("\\+", "%20");
        } else {
            fileName = new String(originalFile.getBytes("UTF-8"), "ISO-8859-1");
        }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
        response.setHeader("Content-Transfer-Encoding", "binary");
        OutputStream out = response.getOutputStream();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            FileCopyUtils.copy(fis, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try { 
                    fis.close(); 
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        out.flush();
    }
}

서버에 다운로드 된 파일을 내 컴퓨터로 다운받을 수 있도록 해줍니다.

반응형