Develop
[JAVA] 파일 다운로드 / 파일 이름 및 확장자 오류 해결 본문
파일 다운로드 구현하면서 알아본 내용
- ajax로 다운로드 하는 방법과 Java에서 다운로드 하는 방법은 다르다
- ajax 사용시 xhr.responseType = "blob" 라는 내용이 들어가야한다
- ajax로는 get방식만 가능하며 post방식은 불가능하다
- <a>태그를 이용한 ajax get방식은 보안에 취약하다
결론
- form submit (post)방법을 사용했다
- form submit 이라고 해서 꼭 페이지를 이동하는 것이 아니므로 써도 됨
- <a> 태그를 이용하여 스크립트 실행, 스크립트에서 form submit 실행
(이 동작도 보안측면에서 괜찮아보이진 않는다)
view.jsp
<form name="Frm" method="post">
<input type="hidden" name="fileId"/>
</form>
<c:forEach var="file" items="${model.fileInfo }">
<c:if test="${file.FILE_TYPE eq 'jpg' || file.FILE_TYPE eq 'jpeg'|| file.FILE_TYPE eq 'png' }">
<img alt="${file.ORG_FILE_NAME }" src="/localFile/${file.FILE_NAME }" width="150px" height="150px">
</c:if>
<br>
${file.ORG_FILE_NAME }
<a onclick="downloadFile('${file.FILE_ID}')">(다운로드)</a> <br>
</c:forEach>
위의 JSP페이지에서 다운로드 버튼 클릭시 downloadFile(파일ID) 함수 실행
JavaScript
function downloadFile(fileId){
var f = document.Frm;
f.fileId.value = fileId;
f.action = "/download_file.do";
f.submit();
}
인수로 받은 파일Id 값을 form에 입력하고 post방식으로 submit
Controller
/**
* 파일 다운로드
*/
@ResponseBody
@RequestMapping("download_file")
public void downloadFile(@RequestParam Map<String,Object> p
, ModelMap map
, HttpServletRequest resquest
, HttpServletResponse response
, HttpSession session) throws Exception{
adminHelpService.downloadFile(p, resquest, response);
}
Service
/**
* 파일 다운로드
*/
void downloadFile(Map p, HttpServletRequest resquest, HttpServletResponse response) throws Exception;
ServiceImpl
@Override
public boolean downloadFile(Map p
, HttpServletRequest resquest
, HttpServletResponse response) throws Exception {
Map dbparams = new Map();
// 파일 정보 조회 (DB)
dbparams.put("fileId", p.get("fileId"));
Map fileInfo = fileDao.selectFileInfo(dbparams);
String fileName = fileInfo.getStr("FILE_NAME"); // 저장된 이름
String orgFileName = fileInfo.getStr("ORG_FILE_NAME"); // 원래 이름
String extension = fileInfo.getStr("FILE_TYPE"); // 파일 확장자
int fileSize = fileInfo.getInt("FILE_SIZE"); // 파일 크기
// 파일 업로드 경로 - C:\\upload\\
// 경로를 나타낼땐 \를 두개 사용
File file = new File("C:\\upload\\" + fileName);
long filelength = file.length();
if(file.isFile() ){ // isFile() 파일이 있으면 true, 없으면 false 반환
try {
// 한글 인코딩
orgFileName = URLEncoder.encode(orgFileName + "." + extension, "UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + orgFileName + ";");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setCharacterEncoding("euc-kr");
response.setHeader("Pragma", "no-cache");
OutputStream os = response.getOutputStream();
// 방법1
FileInputStream fis = new FileInputStream(file);
int i = 0;
byte[] buffer = new byte[1024];
while((i = fis.read(buffer)) != -1){
os.write(buffer, 0, i);
}
fis.close();
// 방법2
byte[] fileByte = FileUtils.readFileToByteArray(file);
os.write(fileByte);
// 공통
os.flush();
os.close();
} catch(FileNotFoundException e){
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
}

view.jsp에서 (다운로드) 글자를 클릭하면
다운로드가 되었지만

파일명과 확장자가 @RequestMapping 명과 같았다...
다운 받은 파일의 확장자를

이렇게 .jpg로 바꿔주고 파일을 열어보니

잘 다운되었음을 알 수 있다
이렇게 했는데도 파일을 못읽는다면 그건 다운이 제대로 안된거임
response.setHeader("Content-Dispositon", "attachment; filename=" + orgFileName + ";");
service단에서 위와같이 다운받을시의 이름을 정해줬는데
왜 이렇게 다운되는건지 한참을 찾았다.
그러다 발견한 글
파일다운로드시 파일명이 세팅되지 않습니다. | 묻고 답하기 | 표준프레임워크 포털 eGovFrame
묻고 답하기 | 표준프레임워크 포털 eGovFrame
처리중입니다. 잠시만 기다려주십시오.
www.egovframe.go.kr
파일 이름이 제대로 다운되지 않는 이유는 인코딩 때문이라고 한다


그래서 service단에 브라우저별 인코딩 처리 부분을 추가해주었다
// 웹 브라우저 종류 조회
String browser = resquest.getHeader("user-agent");
orgFileName = orgFileName + "." + extension;
// 엣지 || IE
if(browser.contains("Edge") || browser.contains("MSIE") || browser.contains("Trident")){
orgFileName = URLEncoder.encode(orgFileName, "UTF-8").replace("\\+", "%20");
response.setHeader("Content-Dispositon", "attachment; filename=\"" + orgFileName);
}
// 크롬 || 오페라
if(browser.contains("chrome") || browser.contains("Opera")){
orgFileName = new String(orgFileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-Dispositon", "attachment; filename=\"" + orgFileName);
}
// 파이어폭스
if(browser.contains("Firefox")){
orgFileName = new String(orgFileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-Dispositon", "attachment; filename=" + orgFileName);
}
근데도 문제 해결이 안됐고 원인을 찾았다................
그냥 오타였다.........
response.setHeader("Content-Dispositon", "attachment; filename=" + java.net.URLEncoder.encode(orgFileName, "UTF-8") + extension + ";");
response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(orgFileName, "UTF-8") + extension + ";");
Content-Disposition 에서 tion이 아닌 ton으로 입력했던것이다..........내 이틀.....
해결돼서 다행인걸까.....
최종 ServiceImpl 내용
@Override
public void downloadFile(Map p
, HttpServletRequest resquest
, HttpServletResponse response) throws Exception {
Map dbparams = new Map();
// 파일 정보 조회
dbparams.put("fileId", p.get("fileId"));
Map fileInfo = fileDao.selectFileInfo(dbparams);
String fileName = fileInfo.getStr("FILE_NAME");
String orgFileName = fileInfo.getStr("ORG_FILE_NAME");
int fileSize = fileInfo.getInt("FILE_SIZE");
String extension = "." + fileInfo.getStr("FILE_TYPE");
File file = new File("C:\\upload\\" + fileName);
if(file.isFile() ){
try {
response.setContentLength(fileSize);
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(orgFileName, "UTF-8") + extension + ";");
response.setContentType("application/octet-stream");
response.setHeader("Content-Transfer-Encoding", "binary");
byte[] fileByte = FileUtils.readFileToByteArray(file);
OutputStream os = response.getOutputStream();
os.write(fileByte);
os.flush();
os.close();
} catch(FileNotFoundException e){
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
}
}
다운로드는 쉬운데 인코딩이 날 괴롭혔다...
'웹 개발 > Java' 카테고리의 다른 글
[JAVA] byte[] 데이터를 String으로 변환후 뷰(JSP)에 출력하기 (0) | 2024.09.04 |
---|---|
[JAVA]구글 OTP 구현 + QR코드 (0) | 2024.09.04 |
QR Code 생성 및 출력하기 (0) | 2024.05.16 |
[JAVA] Bcrypt를 이용하여 비밀번호 암호화하기 (0) | 2024.02.26 |
[JAVA] 비밀번호 암호화 SHA-256 알고리즘 / 레인보우 테이블 / Salt (0) | 2024.02.23 |