Click or drag to resize

여러 파일 업로드

사용자에 의해 선택된 다수의 파일을 비동기 방식으로 업로드합니다. 각 파일 별 업로드 진행률을 출력하며 진행 중인 업로드를 취소할 수 있습니다.

여러 파일 선택 후 업로드

여러 파일을 선택하기 위해서 <input type="file"> 태그에 multiple 속성을 추가합니다. multiple이 추가되어 있으면 파일 선택 대화상자에서 한 번에 여러 파일을 선택할 수 있습니다.

form_multiple.asp HTML
<input id="uploadFiles" type="file" multiple style="width:300px" onchange="uploadFileAdded()">

그리고 파일 추가시 발생하는 onchange 이벤트에서 선택한 파일을 바로 업로드 시킵니다. 여러 개의 파일은 각각의 HTTP 요청으로 비동기 방식으로 업로드가 진행됩니다.

form_multiple.asp JavaScript
// 업로드할 파일이 선택되어 추가될 경우 발생하는 이벤트
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();
}
AJAX 업로드를 담당하는 Uploader 클래스

startUpload는 업로드를 시작시키는 메서드로 FileReader를 사용해 파일을 읽은 후 AJAX을 사용해 파일을 서버로 파일을 전송합니다. 바이너리 데이터 업로드 방식이므로 파일 이름은 file-name 헤더에 기입한 후 전송합니다.

updateProgress 메서드는 업로드 되는 중간에 반복적으로 호출되는 progress 이벤트 처리 메서드로 전송되는 데이터 량 정보를 제공하므로 업로드 진행 정보를 출력하기 위해 사용할 수 있습니다. 전체 데이터 량과 현재 전송된 데이터 량을 사용해 진행 정도를 백분율로 출력합니다.

form_multiple.asp JavaScript
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에는 업로드가 성공적으로 끝난 파일 정보가 저장됩니다.

업로드 처리 ASP 페이지

다수의 파일을 업로드 하는 UI 형태이나 실질적인 업로드는 각 파일 별로 개별 HTTP 요청이 전송되므로 UploadSingle 오브젝트를 사용해 처리할 수 있습니다.

업로드 한 파일은 TempFileManager에 넣어 향후 자동 삭제 될 수 있도록 처리합니다.

upload.asp
<%@ 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
%>