원글 페이지 : 바로가기
자바에서 파일 다운로드를 구현하다 보면 문제가 발생할 때가 있다. 그건 바로 다운로드는 되지만 파일명의 특수문자가 깨진다거나 한글파일명은 다운로드가 안 되는 경우이다. 그래서 오늘은 파일다운로드 할때 어떤 브라우저를 사용하더라도 최대한 다운로드가 실패하지 않게 구현하는 방법을 알아보자. 사용자페이지 ${파일명}
${파일명2}
${파일명3}
파일명을 A 태그로 감싸고 data값에 파일명과 파일경로를 써 주었다. 다운로드 클릭 이벤트가 일어나면 A tag에 있는 data 속성값을 가져와서 변수에 담는다. 미리 만들어둔 download form에 넣고 submit()을 실행한다. 파일 다운로드 컨트롤러 @RequestMapping(value = “/file/download”)
public void download(Model model, HttpServletResponse response, @RequestParam(value = “fileName”) String fileName, @RequestParam(value = “filePath”) String filePath,HttpServletRequest request) throws Exception {
logger.info(“/file/download : ” + filePath + fileName);
try{
request.setCharacterEncoding(“UTF-8”);
fileName = new String(fileName.getBytes(“UTF-8”), “UTF-8”);
File file = new File(filePath, fileName);
if(file.isFile()){
int bytes = (int)file.length();
String header = request.getHeader(“User-Agent”);
if (header.contains(“MSIE”) || header.contains(“Trident”)) {
fileName = URLEncoder.encode(fileName,”UTF-8″).replaceAll(“\\+”, “%20”);
response.setHeader(“Content-Disposition”, “attachment;filename=” + fileName + “;”);
} else {
fileName = new String(fileName.getBytes(“UTF-8”), “ISO-8859-1”);
response.setHeader(“Content-Disposition”, “attachment; filename=\”” + fileName + “\””);
}
response.setContentType( “application/download; UTF-8” );
response.setContentLength(bytes);
response.setHeader(“Content-Type”, “application/octet-stream”);
response.setHeader(“Content-Transfer-Encoding”, “binary;”);
response.setHeader(“Pragma”, “no-cache;”);
response.setHeader(“Expires”, “-1;”);
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream outs = new BufferedOutputStream(response.getOutputStream());
byte[] readByte = new byte[4096];
try{
while((bytes = fin.read(readByte)) > 0){
outs.write(readByte, 0, bytes);
outs.flush();
}
}catch(Exception ex){
}finally{
outs.close();
fin.close();
}
}
}catch(Exception ex){
ex.printStackTrace();
}
} 컨트롤러를 하나만들고 파일명과 파일경로를 받아서 파일 다운로드를 시작한다. 파일명과 파일경로를 이용해 파일객체를 생성한다. file.isFile()을 이용해 파일이 있는지는 체크한후 파일명을 변환해준다. 파일명은 브라우저 중 MSIE로 분류되는 mozila와 Trident로 분류되는 IE는 UTF-8로 변환하고 나머지는 UTF-8 인코딩 형태로 받은 후 ISO-8859-1로 문자를 생성한다. 파일명은 중복이 될수 있기에 보통 pk나 인덱스, 시간 등으로 변환해서 db에 저장한다. 원본파일명이 따로 있다면 header 값 중 Content-Disposition의 fileName 값을 원본파일명으로 넣어주면 된다. 참고 글: https://eastglow.github.io/back-end/2018/11/06/Java-%ED%8C%8C%EC%9D%BC-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%EC%8B%9C-%ED%95%9C%EA%B8%80-%EB%B0%8F-%ED%8A%B9%EC%88%98%EB%AC%B8%EC%9E%90-%EA%B9%A8%EC%A7%90,-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%EB%B6%88%EA%B0%80-%EC%98%A4%EB%A5%98.html