2011年8月25日 星期四

AJAX HTML5 上傳檔案


今天用 firefox 收信的時候,意外發現它可以將桌面上的檔案拖曳進來,然後直接上傳。以往如果之前別人問我能不能用純 ajax 上傳檔案的話,我一定毫不猶豫、斬釘截鐵的說不行。現在在 HTML5 的支援下,看來以後不能再這麼斬釘截鐵了。
照著該文章的寫法做了一次,有部份小修改,順便寫了點中文註解:

<div id="dropzone" style=" border:1px solid black;height:200px;width:200px"></div>

<script type="text/javascript">
    function upload(event) {
        var data = event.dataTransfer;
        
        /* 這個是 RFC2388 的規範,算是二進位資料之間的分隔符號 */
        var boundary = '------multipartformboundary' + (new Date).getTime();
        var dashdash = '--';
        var crlf = '\r\n';

        /* 組出 Request 字串 */
        var builder = '';
        builder += dashdash;
        builder += boundary;
        builder += crlf;
        var xhr = new XMLHttpRequest()

        for (var i = 0; i < data.files.length; i++) {
            var file = data.files[i];

            /* 檔案的標頭 */
            builder += 'Content-Disposition: form-data; name="files"';

            if (file.fileName) {
                builder += '; filename="' + file.name + '"';
            }

            builder += crlf;
            builder += 'Content-Type: ' + file.type;
            builder += crlf;
            builder += crlf;

            /* 檔案內容 */
            builder += file.getAsBinary();
            builder += crlf;

            /* 檔案間的分隔字串 (boundary) */
            builder += dashdash;
            builder += boundary;
            builder += crlf;
        }

        /* Request 結尾 */
        builder += dashdash;
        builder += boundary;
        builder += dashdash;
        builder += crlf;

        /* 直接用 XmlHttpRequest 送出,也就是傳說中的 ajax */
        xhr.open("POST", "/home/upload", true);
        xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=' + boundary);
        xhr.sendAsBinary(builder);


        /* Prevent FireFox opening the dragged file. */
        event.stopPropagation();
        event.preventDefault();
    }

    document.getElementById("dropzone").ondrop = upload;
    document.ondragover = function (event) {event.preventDefault();};
</script>

整段程式最主要就是靠 event.dataTransfer.files 陣列在運作,依序組出整個 HttpRequest 的內容,然後再用 ajax 回傳到伺服器端,還可以一次拖曳多個檔案:
image

就這樣,沒有 PostBack、瀏覽器也不會閃一下,漂亮的完成以往要用 Silverlight 、Flash 才辦得到的檔案上傳。可惜我用習慣的 IE 要等到 10 才會開始支援。
另外,在該篇文章底下討論串還看到這個連結,看起來似乎能夠更方便的使用 ajax 上傳功能。








沒有留言:

張貼留言