다운로드하기
일반적으로 브라우저가 서버로 GET/POST 요청을 하면, 서버는 응답 데이터를 반환하는데, 이 응답 데이터가 브라우저가 직접 해석하여 화면에 표현할 수 없는 형식인 경우에는 이 응답 데이터를 파일로 다운로드한다. Anchor(a) 태그에 설정된 하이퍼링크 값을 예로 들면, 브라우저가 해석할 수 있는 이미지(jpg) 파일인 경우, 새창(또는 탭) 혹은 현재 창에 이미지가 보여지지만, zip 파일의 경우에는 바로 다운로드를 수행하는 것을 볼 수 있다. 만일 jpg 파일을 열지 않고 디스크로 바로 다운로드하려면 브라우저 자체 기능(컨텍스트 메뉴 - 다른 이름으로 저장)에 의존하거나 서버에서 브라우저가 강제로 다운로드하도록 하는 응답 헤더를 실어 보내야 한다.
주의) macOS에서는 다운로드 받을 파일이 이미지이거나 zip인 경우, 자동으로 연결 프로그램을 실행하기도 한다. HTML5에는 대상 형식(mime type)에 상관없이 강제로 파일을 다운로드 하도록 하는 속성이 새로 추가되었다. 그러나 모든 브라우저에서 이 기능을 지원(2016년 초 기준)하지 않고 있기 때문에, HTML 또는 JavaScript 만을 가지고 파일을 디스크로 다운로드할 수 없다.
DEXTUploadX5에서 파일을 다운로드 받으려할 때 브라우저 특성을 그대로 영향 받기 때문에, 여러 브라우저에서 파일을 동일하게 다운로드(열지 않고)받으려면, 서버의 응답 헤더을 사용해야 한다.
- 다운로드 항목 등록하기
-
DEXTUploadX5는 다운로드할 항목을 반드시 가상 파일로 등록해야 한다.
가상 파일이란 사용자 로컬 PC에 존재하지 않으며, 실체가 없는 가상의 파일을 말한다. 즉 실제로 로컬에 존재하지 않는 파일이므로, 파일 업로드 대상이 아니다. 일반적으로 가상 파일은 이미 업로드한 파일에 대한 정보를 남기는 용도로 사용하곤 한다. (서버에 존재하는 파일이라는 표시)
가상 파일을 등록하려면 addVirtualFile 함수를 사용하거나 addVirtualFileList 함수를 사용한다.
- vindex: 가상 파일을 구분 짓는 유일한 키로써, 어떤 형식이라도 상관이 없지만, 중복되지 않아야 한다. (필수항목)
- name: 가상 파일의 이름이다. (필수항목)
- size: 가상 파일의 크기이며 byte 단위를 사용한다. (필수항목)
- lock: 잠금 상태가 true이면 파일을 삭제할 수 없다.
var dx = dx5.get(id); // 개별로 등록할 때 dx.addVirtualFile({ vindex: "IDX0001", name: "가상파일.txt", size: 12345 }); dx.addVirtualFile({ vindex: "IDX0002", name: "잠긴-가상파일.txt", size: 45678, lock: true }); dx.addVirtualFile({ vindex: "IDX0003", name: "코스모스.jpg", size: 195779 }); // 여러 개를 한 번에 등록할 때 dx.addVirtualFileList([ { vindex: "IDX0001", name: "가상파일.txt", size: 12345 }, { vindex: "IDX0002", name: "잠긴-가상파일.txt", size: 45678, lock: true }, { vindex: "IDX0003", name: "코스모스.jpg", size: 195779 } ]);가상 파일이 다운로드 대상이 되려면 json 속성 중에 url 속성(또는 downUrl 속성)이 설정되어 있어야 한다.
// 다운로드 경로 정보가 없어서 다운로드할 수 없는 가상 파일이다. dx.addVirtualFile({ vindex: "IDX0001", name: "가상파일.txt", size: 12345 }); // 다운로드 경로가 있으면 다운로드할 수 있다. dx.addVirtualFile({ vindex: "IDX0003", name: "서강대교_509147.jpg", size: 509147, url: "http://domain/file/attach/서강대교_509147.jpg" }); dx.addVirtualFile({ vindex: "IDX0003", name: "서강대교_509147.jpg", size: 509147, url: "http://domain/common-download.do?key=FID0001" });url(또는 downUrl) 속성 값은 반드시 스키마(http, https)로 시작하는 웹 URL이어야 한다. URL에 한글이나 특수 문자가 들어간 경우에는 대상을 못 찾거나, 다운로드가 실패하는 경우가 있다. (반드시 안되는 것이 아니라, 브라우저 종류 혹은 버전마다 차이가 있을 수 있다.) 이런 경우 다국어 및 특수 문자가 사용되는 구간을 encodeURIComponent 자바스크립트 함수를 사용하여 인코딩을 하면 된다.
dx.addVirtualFile({ vindex: "IDX0003", // 인코딩 불필요 name: "서강대교_509147.jpg", size: 509147, // 인코딩 필요 downUrl: "http://domain/file/attach/" + encodeURIComponent("서강대교_509147.jpg") }); - 버튼 연결하기
-
DEXTUploadX5 컴포넌트는 url(또는 downUrl)이 설정된 항목만 다운로드 버튼을 표시한다. 만약 대상에 표시된 다운로드 버튼을 사용하지 않고 외부 HTML 버튼을 사용하고자 한다면 스크립트를 사용하여 컴포넌트 기능을 연결해줘야 한다.
<button type="button" onclick="download('component-id');">다운로드</button> <script> function download(id) { // 플래그 값에 따라 다운로드를 수행한다. // AUTO: 첫 번째 가상 파일을 다운로드한다. // SELECTED: 선택된 대상 중에 첫 번째 가상 파일을 다운로드한다. // CHECKED: 체크된 대상 중에 첫 번째 가상 파일을 다운로드한다. dx5.get(id).download("AUTO"); } </script>복잡한 스크립트를 사용하지 않고서 컴포넌트 로드 시점에 자동 바인딩이 되는 기능도 함께 제공하고 있다.
<button type="button" id="btn-down-auto">다운로드</button> <button type="button" id="btn-down-selected">선택 다운로드</button> <button type="button" id="btn-down-checked">체크 다운로드</button> <script> dx5.create({ ..., // 컴포넌트가 생성될 때, 파일 다운로드 기능이 자동으로 연결하도록 한다. btnDownloadAuto: "btn-down-auto", btnDownloadSelected: "btn-down-selected", btnDownloadChecked: "btn-down-checked" }); </script>자동 바인딩 기능은 매우 편리하나, 복잡한 기능을 구현하기에는 적합치 않을 수 있다.
- 서버측 처리
-
// 다운로드할 대상이 웹 주소로 노출되어 있는 경우 { vindex: "IDX0003", name: "서강대교_509147.jpg", size: 509147, url: "http://domain/files/attach/서강대교_509147.jpg" }다운로드 하려는 대상이 웹 주소를 가지고 있다면, 대상을 호출했을 때, 다운로드가 가능하도록 서버에서는 응답 헤더에 "Content-Disposition: attachment"를 추가하면 된다.
다운로드를 하기 위한 웹 서버 혹은 WAS 별 응답 헤더 설정 방법은 본 매뉴얼에서 제공하지 않는다.
만일 대상이 웹 주소를 가지고 있지 않거나, URL 은닉이 필요한 경우라면 웹 애플리케이션을 사용하여 다운로드를 할 수 있도록 서비스를 구성해야 한다.
// 다운로드할 대상이 웹 주소에 없거나, URL 은닉 처리를 위해서 웹 애플리케이션을 사용하는 경우 { vindex: "IDX0003", name: "서강대교_509147.jpg", size: 509147, downUrl: "http://domain/files/service/common-download.do?key=FID0001" }다음은 자바 JSP 혹은 서블릿 환경에서 DEXTUploadNJ 제품을 사용하여 서비스를 구현한 경우이다. 주어진 매핑 서블릿(JSP도 가능)에서 FileDownload 클래스를 사용하여 다운로드를 처리할 수 있다.
# 서버 측 설정이다. File target = null; String key = request.getParameter("key"); if (key.equals("FID0001")) target = new File(fileRoot, "서강대교_509147.jpg"); else if (key.equals("FID0002")) target = new File(fileRoot, "우도해변_239826.jpg"); else if (key.equals("FID0003")) target = new File(fileRoot, "코스모스 (빈공간) 195779.jpg"); if (target == null || target.exists() == false || target.isFile() == false) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "주어진 키에 해당하는 파일 정보가 없다."); return; } try { // FileDownload 객체를 생성한다. FileDownload dextnj = new FileDownload(); // 인코딩을 UTF-8로 설정한다. response.setCharacterEncoding("UTF-8"); // 파일을 첨부 파일 형식으로 다운로드한다. dextnj.download(request, response, target); } catch (Exception e) { throw new ServletException(e); }다음은 자바 Spring 웹 프레임워크 환경에서 DEXTUploadNJ 제품을 사용하여 서비스를 구현한 경우이다. 주어진 요청에 매핑된 컨트롤러의 메소드에서 DEXTUploadNJFileDownloadView 클래스를 사용하여 다운로드를 처리할 수 있다.
# 서버 측 설정이다. File target = null; String fileRoot = request.getSession().getServletContext().getRealPath("/files/attach"); if (key.equals("FID0001")) target = new File(fileRoot, "서강대교_509147.jpg"); else if (key.equals("FID0002")) target = new File(fileRoot, "우도해변_239826.jpg"); else if (key.equals("FID0003")) target = new File(fileRoot, "코스모스 (빈공간) 195779.jpg"); // 인코딩을 UTF-8로 설정한다. response.setCharacterEncoding("UTF-8"); if (target == null || target.exists() == false || target.isFile() == false) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "주어진 키에 해당하는 파일 정보가 없다."); return null; } else { // DEXTUploadNJFileDownloadView 뷰 클래스를 사용하여 파일을 다운로드할 수 있다. DEXTUploadNJFileDownloadView dextnj = new DEXTUploadNJFileDownloadView(target); return new ModelAndView(dextnj); } - 다중 파일 다운로드(1.1.0.0 버전부터 지원)
-
앞서 설명한 다운로드 방법은 화면 안의 다운로드 아이콘을 클릭하거나, download, downloadById 메소드를 사용하여 한 개씩 파일을 다운로드하는 방법을 설명한 것이다.
HTML5는 Sandbox 문제로 인하여 로컬 자원에 접근이 용이한 플러그인 기술을 사용하지 않고서는 다중 파일 다운로드를 할 수 없는 것이 일반적인 생각이다. 그러나 파일 용량에 제한을 두며, 다운로드 경로 설정을 브라우저에게 맡긴다면, 순차적으로 여러 파일을 다운로드하는 다중 파일 다운로드 기능을 순수 브라우저 기술만으로도 구현할 수 있다.
다중 파일 다운로드는 다운로드를 수행하는 아이콘이 따로 없기 때문에 download 메소드를 직접 호출하여 사용한다.
download 메소드의 두 번째 값이 true이면 다중 파일 다운로드 방식으로 다운로드 작업을 수행한다.
<button type="button" onclick="download('component-id');">다운로드</button> <script> function download(id) { // 플래그 값에 따라 다운로드를 수행한다. // AUTO: 모든 가상 파일을 다운로드한다. // SELECTED: 선택된 대상 중에 가상 파일 모두를 다운로드한다. // CHECKED: 체크된 대상 중에 가상 파일 모두를 다운로드한다. dx5.get(id).download("AUTO", true); } </script>다중 파일 다운로드 방식을 사용할 때에는 서버 컴포넌트를 사용할 때는 캐시 옵션 조정이 필요하다.
서블릿(JSP) 환경에서 FileDownload 클래스를 사용하여 다운로드를 처리할 때,
# 서버 측 설정이다. ... // FileDownload 객체를 생성한다. FileDownload dextnj = new FileDownload(); // 인코딩을 UTF-8로 설정한다. response.setCharacterEncoding("UTF-8"); // dextnj.download(request, response, target); // 단일 파일 다운로드가 아닌 다중 파일 다운로드에서는 캐시를 사용하지 않아야 한다. (useClientCache 파라미터 값을 false로 설정) dextnj.download(request, response, target, target.getName(), "application/octet-stream", false, false);자바 Spring 웹 프레임워크 환경에서 DEXTUploadNJFileDownloadView 클래스를 사용하는 경우는 다음과 같는다.
# 서버 측 설정이다. ... // DEXTUploadNJFileDownloadView 뷰 클래스를 사용하여 파일을 다운로드할 수 있다. DEXTUploadNJFileDownloadView dextnj = new DEXTUploadNJFileDownloadView(target); // 캐시를 false로 설정한다. dextnj.setUseClientCache(false); return new ModelAndView(dextnj);
단일 파일 다운로드와 달리 다중 파일 다운로드는 브라우저 성능 문제로 인하여 다운로드하는 파일의 크기에 제한을 두도록 하였다. 기본값은 100MB이며, 파일 크기를 그 이상 허용하려면 setLimitMultiDownloadSize 함수를 사용하여 제한된 크기를 변경하면 된다.
그러나 이 함수는 제품상에서 다운로드가 허용되는 대상의 크기를 변경하는 것이지, 로컬 환경에 관계없이 다운로드가 성공하도록 브라우저의 성능을 향상시키는 기능을 제공하는 것이 아니다. HTML5의 기능을 사용하여 파일을 연속적으로 다운로드하려면, 일시적으로 다운로드 대상을 메모리에 로드하기 때문에, 동영상 파일과 같이 용량이 큰 파일들은 적절한 다중 파일 다운로드 대상이 아니다. 그러므로 대용량 다운로드, 이어 받기와 같은 기능이 필요하다면, HD 응용프로그램을 사용하는 것을 권장한다.
// 다운로드 제한 크기를 300MB로 설정한다. dx.setLimitMultiDownloadSize(1024 * 1024 * 300);
- 단일, 다중 파일 다운로드의 공통점과 차이점
-
단일 다중 다운로드 경로(로컬 PC)는 브라우저 설정에 따라 결정되므로 컴포넌트에서 이를 변경할 수 없다. 다운로드 경로에 동일한 파일명을 갖는 파일이 있다면, 브라우저가 자동으로 suffix(번호같은)를 붙인다. 대용량 다운로드: 다운로드할 수 있는 파일 용량에 기본적으로 제한이 없다.
- 클라이언트(PC)는 GB 단위의 파일을 저장할 수 있는 파일 시스템이어야 한다.
- 원본 파일을 갖는 웹 또는 WAS 서버가 GB 단위의 파일을 내려보낼 수 있어야 한다.
다운로드할 수 있는 파일 용량에 제한(기본값은 100MB)이 있다.
setLimitMultiDownloadSize 함수를 제한 크기를 변경할 수 있다. (다운로드가 허용되는 파일의 크기를 변경하는 것으로써, 브라우저의 성능을 높이는 기능이 아니다.)
대상을 다운로드(GET)하기 전에, HEAD 요청을 미리 보내어, 파일에 대한 존재 유무를 확인한다. 다중 파일 다운로드는 파일의 존재 유무를 확인하기 위한 HEAD 요청을 보내지 않는다. (3.8.0.0 버전부터는 다중 파일 다운로드에서도 HEAD 요청을 보낸다.) 대상의 형식에 따라 첨부 형태로 다운로드 안될 수 있으므로, 서버나 서버 컴포넌트를 사용하여 Content-Disposition: attachment 응답 헤더를 설정해야 한다. 다중 파일 다운로드는 Content-Disposition 응답 헤더 설정과 상관없이 대상을 다운로드할 수 있다. 다운로드 진행창을 제공하지 않는다. 다운로드 진행창을 제공한다.
브라우저가 최종적으로 파일을 저장하는 단계(제어가 안되는)가 존재하기 때문에, 다운로드가 완료되었다하더라도, 브라우저에서 다이얼로그를 띄우거나, 임시 파일을 복사하는 등의 추가 작업이 있을 수 있다.
- HTML5를 지원하는 모던 브라우저(Edge, Safari, Chrome, Firefox, Opera)에서 모두 지원한다.
- iOS, iPad에서는 Safari(13 버전 이상)에서만 단일 파일 다운로드를 지원한다.
- macOS인 경우에는 Safari 10.1 이상에서 지원한다.
- iOS, iPad에서는 Safari 17 버전 이상만 지원하며 다운로드할 파일의 수가 적은 경우(10개 이하)에만 파일 누락 없이 다운로드할 수 있다.
버튼과 자동으로 바인딩하는 기능을 지원한다. 다중 파일 다운로드는 버튼과 자동으로 바인딩하는 기능을 지원하지 않는다. 다중 파일 다운로드는 기능은 문서와 같이 파일의 크기가 작은 파일들을 한꺼번에 받을 경우에 용이하다. 그러므로 대용량 파일을 다운로드하거나, 이어 받기 및 여러 다운로드 옵션이 필요하다면, HD 응용프로그램을 사용하는 것을 권장한다.