파일다운로드 완료 시 로딩바 종료
* 현재 pdf다운로드 요건 :
1. html to pdf 다운로드 기능
2. 다건의 데이터 클릭 후 다운로드 버튼 누를 경우 다건의 html 페이지를 하나의 pdf파일로 다운로드
-> 서버단에서 html 페이지를 읽어와 하나의 pdf파일로 합치기 때문에 로딩시간이 길다.
* 이슈사항 :
URL 경로를 통해 파일을 다운로드 받는 것이 아닌, 빽단에서 response의 header를 아래와 같이 BufferOutputStream으로 출력할 경우
파일 다운로드 완료 타이밍을 어떻게 확인할 수 있나?
if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > -1 || request.getHeader("User-Agent").toLowerCase().indexOf("edge") > -1 || request.getHeader("User-Agent").toLowerCase().indexOf("rv:11.0") > -1 ) { response.setHeader("Content-Disposition", "attachment; filename=\"" + (URLEncoder.encode(downloadPdfFilename,"UTF-8").replaceAll("\\+","%20")) + "\""); } else { response.setHeader("Content-Disposition", "attachment; filename=\"" + (new String(downloadPdfFilename.getBytes("UTF-8"), "8859_1")) + "\""); } //out.clear(); //out = pageContext.pushBody(); BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream()); int read = 0; while ((read = in.read()) != -1) { os.write(read); } // response.flushBuffer(); in.close(); // os.flush(); os.close(); file.delete();
* 시도해본 방법
1. response.getWriter().print() 메서드를 통해 script로 로딩바 종료 메서드 호출.
StringBuffer script = new StringBuffer(); script.append("<script type="\"text/javascript\"">"); script.append("tmsComm.destroyProgressBar();"); script.append("</script>"); response.getWriter().print(script.toString());
-> response를 통해 buffer stream으로 파일도 출력하고, text로도 출력해 script단을 호출하려 했으나
다음과 같은 에러 발생(java.lang.IllegralStateException)
구글링 결과 response는 2가지 형식으로 출력이 불가능하다. 이미 stream형태로 출력하기 때문에 text로 출력 불가
(상식적으로도 그러는게 당연)
2. jsp단에서 직접 <script>코드 추가
20row의 sout은 back단의 시스템 로그에 찍히지만,
23row의 alert는 response로 이미 파일 스트림을 출력했으므로 front단은 읽지 않아서 alert이 찍히지 않는다.
따라서 이 방법으로도 구별 불가.
3. form의 target을 iframe으로 주어서 iframe onload(파일다운로드 작업 완료) 이벤트 시 호출
// 1번 방법 $(document).on("load","#hideIframe",function (){ alert("aaaa"); tmsComm.destroyProgressBar(); }); // 2번 방법 $("#hideIframe").on("load",function () { alert("aaaa"); tmsComm.destroyProgressBar(); }); // 3번 방법 document.getElementById("hideIframe").onload = function () { alert("ccccccc"); };
-> 1~3번 방법까지 다 시도 해봤으나 onload 이벤트 메소드 자체가 호출 되지가 않는다.
-> 구글링 결과 stackoverflow형님에게서 다음과 같은 결과를 얻을 수 있었다.
Unfortunately it is not possible to use an iframe's onload event in Chrome if the content is an attachment.
안타깝게도 콘텐츠가 첨부 파일 인 경우 Chrome에서 iframe onload 이벤트를 사용할 수 없습니다.
4. ajax 호출(?) -> ajax의 경우 string/xml통신 기반이다. 따라서 response값을 string값으로 url주소를 넘겨주어서 파일 다운로드가 가능하지만
언제 다운로드가 완료됬는지는 확인 불가. 게다가 지금 상황은 response값을 파일 스트림으로 곧바로 넘겨주는 경우이다.
* 해결책
약 4~5시간의 뻘짓 끝에 stackoverflow형님의 도움을 받아 해결.
형님 왈 : I hate this, but I couldn't find any other way than checking whether it is still loading or not except by checking at intervals.
나도 이 방법이 싫지만 아직 로딩 중인지 아닌지를 확인하는 방법을 이 방법 외에는 어떤 방법도 찾지 못했다.
var timer = setInterval(function () { iframe = document.getElementById('iframedownload'); var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; // Check if loading is complete if (iframeDoc.readyState == 'complete' || iframeDoc.readyState == 'interactive') { tmsComm.destroyProgressBar(); clearInterval(timer); return; } }, 4000);
이 방법은 파일 다운로드 시에 4초에 1번씩 iframe의 상태값을 확인해서 iframe상태가 complete이거나 interactive인 경우 timer와 로딩바를 중단시키는 방법이다.
결국 찾다찾다 이 방법을 채택하였지만 완벽하지 못하다. 가장 좋은 방법은 이 것일 거 같다.
※ response를 파일 스트림으로 넘기는 것이 아니라 URL로 던져주어서 서버의 파일을 다운로드 받게 하고 서버단에서는 특정날짜/특정시간에 PDF파일들을 삭제하는 쉘 스크립트를 작성하는 것
이 부분은 고도화 작업시에 다시 진행할 예정이다.
'Javascript' 카테고리의 다른 글
IE에서 iframe(레이어 팝업) reload 시에 input text 태그 미작동 오류 (0) | 2020.03.03 |
---|---|
jsp에서 jqery template을 사용할 때 (0) | 2019.02.18 |
jquery event에 parameter를 전달하고자 할 때 (0) | 2019.01.24 |
opener를 사용하지 못할 때 (0) | 2018.04.12 |