여러 파일 업로드 |
사용자에 의해 선택된 다수의 파일을 비동기 방식으로 업로드합니다. 각 파일 별 업로드 진행률을 출력하며 진행 중인 업로드를 취소할 수 있습니다.
여러 파일을 선택하기 위해서 <input type="file"> 태그에 multiple 속성을 추가합니다. multiple이 추가되어 있으면 파일 선택 대화상자에서 한 번에 여러 파일을 선택할 수 있습니다.
<input id="uploadFiles" type="file" multiple style="width:300px" onchange="uploadFileAdded()">
그리고 파일 추가시 발생하는 onchange 이벤트에서 선택한 파일을 바로 업로드 시킵니다. 여러 개의 파일은 각각의 HTTP 요청으로 비동기 방식으로 업로드가 진행됩니다.
// 업로드할 파일이 선택되어 추가될 경우 발생하는 이벤트 function uploadFileAdded() { var uploadFiles = document.getElementById("uploadFiles") for (var i = 0; i < uploadFiles.files.length; i++) { var file = uploadFiles.files[i]; // 비동기 파일 업로드를 시작한다. var uploader = new Uploader(file); uploader.startUpload(); } // 폼을 리셋해서 uploadFiles에 출력된 선택 파일을 초기화시킨다. document.getElementById("uploadForm").reset(); }
startUpload는 업로드를 시작시키는 메서드로 FileReader를 사용해 파일을 읽은 후 AJAX을 사용해 파일을 서버로 파일을 전송합니다. 바이너리 데이터 업로드 방식이므로 파일 이름은 file-name 헤더에 기입한 후 전송합니다.
updateProgress 메서드는 업로드 되는 중간에 반복적으로 호출되는 progress 이벤트 처리 메서드로 전송되는 데이터 량 정보를 제공하므로 업로드 진행 정보를 출력하기 위해 사용할 수 있습니다. 전체 데이터 량과 현재 전송된 데이터 량을 사용해 진행 정도를 백분율로 출력합니다.
function Uploader(file) { var self = this; this._file = file; this._serverFileKey = ""; // 업로드 성공시 서버에서 전달된 고유 값을 저장(이 예제에서는 파일 이름이 사용됨) this._xhr = new XMLHttpRequest(); this._xhr.addEventListener("load", transferComplete); this._xhr.upload.addEventListener("progress", updateProgress); this._xhr.upload.addEventListener("error", transferFailed); // uploadList에 업로드 아이템을 하나 추가한다. var li = document.createElement("li"); var fileNameSpan = document.createElement("span"); var blankSpan = document.createElement("span"); var progressSpan = document.createElement("span"); var cancelLink = document.createElement("a"); fileNameSpan.innerHTML = file.name; blankSpan.innerHTML = " "; cancelLink.setAttribute("href","#"); cancelLink.innerHTML = "[X]"; li.appendChild(fileNameSpan); li.appendChild(blankSpan); li.appendChild(progressSpan); li.appendChild(cancelLink); var uploadList = document.getElementById("uploadList"); uploadList.appendChild(li); // 취소 버튼 클릭 이벤트 cancelLink.onclick = function () { // 업로드 취소 self._xhr.abort(); // 업로드 파일 목록에서 제거 self._removeUploadItem(); }; // 업로드를 시작시킨다. this.startUpload = function () { var reader = new FileReader(); var fileName = this._file.name; var xhr = self._xhr; // FileReader에서 파일 데이터를 읽은 경우 발생하는 이벤트 reader.onload = function(evt) { // AJAX 요청을 생성해 전송한다. xhr.open("POST", "upload.asp", true); // 파일 이름은 file-name에 명시한다. xhr.setRequestHeader("file-name", encodeURIComponent(fileName)); xhr.send(evt.target.result); }; // 비동기 파일 읽기 시작 reader.readAsArrayBuffer(file); } this._removeUploadItem = function () { uploadList.removeChild(li); uploadFileList.remove(self._serverFileKey); } // AJAX 데이터가 전송되는 동안 수시로 발생하는 이벤트로 진행 과정을 출력한다. function updateProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.ceil(evt.loaded / evt.total * 100); progressSpan.innerHTML = percentComplete + "%"; } } // 한 파일 업로드가 완료되면 호출되는 이벤트로 성공시 고유 값(이 예제에서는 파일 이름)이 반환된다. function transferComplete() { if (this.status == 200) { progressSpan.innerHTML = ""; self._serverFileKey = this.responseText; uploadFileList.add(self._serverFileKey); } else { alert("ERROR : " + this.responseText); self._removeUploadItem(); } } function transferFailed(evt) { self._removeUploadItem(); console.log("An error occurred while transferring the file."); } }
파일 이름 옆에 있는 [X]를 클릭할 경우 cancelLink.onclick 이벤트가 발생하며 AJAX 전송을 취소하고 리스트에 출력되어 있는 파일 이름을 삭제합니다. 개별 파일에 대한 업로드가 완료되면 서버 페이지로부터 업로드 파일에 대한 고유 키 값(이 예제는 파일 이름을 사용)을 받아와 uploadFileList에 저장합니다. uploadFileList에는 업로드가 성공적으로 끝난 파일 정보가 저장됩니다.
다수의 파일을 업로드 하는 UI 형태이나 실질적인 업로드는 각 파일 별로 개별 HTTP 요청이 전송되므로 UploadSingle 오브젝트를 사용해 처리할 수 있습니다.
업로드 한 파일은 TempFileManager에 넣어 향후 자동 삭제 될 수 있도록 처리합니다.
<%@ CodePage=65001 Language=VBScript %> <% UploadPath = "C:\Temp\Upload" Set upload = Server.CreateObject("TABSUpload4.UploadSingle") upload.FileNameHeader = "file-name" '하나의 파일에 대한 바이너리 업로드 데이터를 처리한다. upload.Start "C:\Temp" '처리한 데이터를 실제 파일로 저장한다. upload.Save UploadPath, false Response.Write upload.ShortSaveName 'AJAX으로 업로드된 파일은 가비지 파일이 될 수 있으므로 TempFileManager에서 일정 시간(5시간) 동안만 유지시킨다. Set tmgr = Server.CreateObject("TABSUpload4.TempFileManager") tmgr.AddFile upload.SaveName, 60 * 5 %>