Click or drag to resize

바이너리 파일 업로드

HTML5의 FileAPI와 AJAX을 사용하면 폼 서브밋과는 별도로 파일 업로드를 진행할 수 있습니다. 이 경우 multipart/form-data를 생성할 필요 없이 FileAPI를 사용해 파일 데이터를 직접 읽어서 웹 서버로 전송할 수 있습니다.

Note Note

HTML5의 FileAPI를 사용하기 위해서는 웹 브라우저가 해당 기능을 제공해야 합니다. 현재 PC 브라우저인 Internet Explorer 10/11, Chrome, Firefox, Safari에서 사용 가능합니다. 안드로이드, IOS 기반 브라우저에서도 사용 가능합니다.

간단한 업로드 파일 전송

FileAPI 클래스 중 FileReader 클래스를 사용해 파일 데이터를 직접 읽을 수 있습니다. 읽은 파일 이름과 파일 데이터를 사용해 AJAX 요청을 생성해 서버로 전송하고 그 응답을 받아 리스트에 출력합니다.

이 같은 방식의 업로드는 HTTP 본문이 파일의 바이너리 데이터로 구성되므로 그 외의 추가 정보는 URL의 GET 파라미터 또는 HTTP 헤더를 통해 서버로 전송할 수 있습니다. 탭스 업로드는 file-name 이라는 명칭의 헤더에 파일 이름을 전송하는 방식을 사용합니다. 파일 이름은 반드시 encodeURIComponent() 함수를 사용해 인코딩해야 한글 이름이 손상되지 않고 서버로 전송됩니다.

form_simple.asp JavaScript
function Uploader(file) {
    this._file = file;
    this._xhr = new XMLHttpRequest();
    this._xhr.addEventListener("load", transferComplete);        

    // 파일 하나에 대한 업로드를 시작한다.
    this.startUpload = function () {
        var reader = new FileReader();
        var fileName = this._file.name;
        var xhr = this._xhr;

        // FileReader에서 파일 내용을 모두 읽은 경우 AJAX으로 전송한다.
        reader.onload = function(evt) {
            xhr.open("POST", "upload.asp", true);
            // 파일 이름은 file-name에 명시한다.
            xhr.setRequestHeader("file-name", encodeURIComponent(fileName));
            xhr.send(evt.target.result);
        };
        reader.readAsArrayBuffer(file);            
    }

    function transferComplete() {
        // 성공적으로 업로드된 경우 UI에 출력한다.
        if (this.status == 200) {
            var li = document.createElement("li");
            li.innerHTML = this.responseText;
            document.getElementById("resultList").appendChild(li);
        }
    }
}

function Upload() {
    var uploadFiles = document.getElementById("uploadFiles");
    var uploader = new Uploader(uploadFiles.files[0]);
    uploader.startUpload();
}
form_simple.asp HTML
<form>
  <input id="uploadFiles" type="file" style="width:300px">
  <br />
  <br />
  <input id="uploadBtn" type="button" value="업로드" onclick="Upload()"/>

  <h3>업로드 결과</h3>
  <ul id="resultList"></ul>
</form>
AJAX HTTP 요청

위 코드에서 생성된 업로드 AJAX HTTP 요청을 캡처해 보면 아래와 같습니다. file-name 헤더에 파일 이름이 인코딩되어 전송되고 HTTP 본문은 파일 자체 데이터만 전송됩니다.

이 데이터를 ASP 페이지에서 받아서 처리할 수 있는 오브젝트가 TABSUpload4.UploadSingle 오브젝트입니다. 기존 TABSUpload4.Upload 오브젝트는 multipart/form-data 형식의 업로드 데이터를 처리하는 것으로 바이너리 형식의 AJAX HTTP 요청을 처리할 수 없습니다.

HTTP 요청
POST /upload.asp HTTP/1.1
Accept: */*
file-name: (%EA%B3%B5%EC%9C%A0%EC%9A%A9)%EC%B6%9C%EA%B3%A0%ED%99%95%EC%9D%B8%EC%84%9C(%ED%86%B5%ED%95%A9)_%EC%9D%BC%EC%9A%94%EC%9D%BC.xlsx
Accept-Language: ko-KR
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Length: 77596
Connection: Keep-Alive
Cache-Control: no-cache

[binary file data]
업로드 처리 ASP 페이지

이러한 방식의 바이너리 업로드 데이터는 하나의 파일 데이터만 전송되고 여타 다른 폼 데이터는 전송되지 않으므로 매우 간단한 코드로 처리될 수 있습니다. TABSUpload4.UploadSingle 오브젝트를 생성한 후 Start 메서드를 호출합니다. Start 에서는 바이너리 데이터를 읽어서 임시 파일 형태로 저장하고 HTTP 헤더로 전달되는 파일 이름을 디코딩합니다. 모든 데이터를 받은 후 Save 또는 SaveAs 메서드를 호출해 원하는 위치로 파일을 옮겨 저장합니다.

upload.asp
<%@ CodePage=65001 Language=VBScript %>
<%
UploadPath = "C:\Temp\Upload"

Set upload = Server.CreateObject("TABSUpload4.UploadSingle")

'하나의 파일에 대한 바이너리 업로드 데이터를 처리한다.
upload.Start "C:\Temp"
'처리한 데이터를 실제 파일로 저장한다.
upload.Save UploadPath, false

Response.Write upload.ShortSaveName
%>
임시 파일 처리

AJAX을 사용한 업로드 UI는 일반적으로 파일 업로드와 폼 데이터 제출(Submit)이 서로 다른 HTTP 요청으로 처리합니다. AJAX으로 파일을 업로드하고 그 결과(파일 고유 키 값)를 받아와서 저장하고 있다가 폼 데이터 제출시 함께 보내 최종 처리를 합니다.

예를 들어 게시판에 글을 쓸 경우 팝업 윈도우에서 이미지 파일 업로드를 AJAX으로 처리하고 그 결과를 폼 페이지로 보냅니다. 글 작성을 완료한 후 제출하게 되면 글 데이터는 DB에 저장하고 이미지 파일은 파일 디렉터리에 저장하게 됩니다. 이 과정에서 사용자가 글 작성을 완료하지 않고 브라우저를 종료한다면 업로드 된 이미지 파일은 게시판 글과 연결되지 않은 채로 서버의 어딘가에 저장되어 있게 됩니다. 즉, 가비지 파일이 생성됩니다.

이 문제를 해결하기 위해 탭스 업로드는 TempFileManager라는 오브젝트를 제공합니다. 업로드 완료 후 임시 디렉터리에 저장된 이미지를 TempFileManager에 넣어 둡니다. 최종 폼이 제출되고 글 저장이 될 때 이미지 파일을 최종 목적지로 복사합니다. 최종 폼 제출이 되지 않을 경우 TempFileManager는 일정 시간 뒤 자동으로 해당 파일을 삭제해 서버에 가비지 파일이 생성되지 않도록 합니다. TempFileManager를 사용하기 위해서는 TABS Upload 5 Utility Service가 실행되고 있어야 합니다.

upload.asp
<%@ CodePage=65001 Language=VBScript %>
<%
UploadPath = "C:\Temp\Upload"

Set upload = Server.CreateObject("TABSUpload4.UploadSingle")

'하나의 파일에 대한 바이너리 업로드 데이터를 처리한다.
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
%>