@blog.justoneplanet.info

日々勉強

もっとFile APIを使ってXMLHttpRequestと組み合わせてみる

XMLHttpRequest Level2ではバイナリデータもアップロードできるようになった!ヽ(=´▽`=)ノ

■ソース

基本的には前回と同じコードを利用している。

<p ondragstart="dragstart(event)" ondragenter="dragenter(event);" ondragover="dragover(event);" ondrop="drop(event);">You drop some images, here!</p>
<div id="preview"></div>

次にJavaScriptコード。

function dragStart(e){
    //e.preventDefault();
}
function dragEnter(e){
    //e.preventDefault();
}
function dragOver(e){
    e.preventDefault();
}
function drop(e){
    var files = e.dataTransfer.files;
    for(var i = 0; i < files.length; i++){
        var request = new XMLHttpRequest();
        request.upload.onprogress = function(e){
            document.getElementById('progress').style.width = ((e.loaded / e.total) * 100 + "%");
        }
        request.upload.onload = function(e){
            document.getElementById('progress').style.width = '0px';
            alert('finished');
        }
        request.open('post', "./index.html");
        request.send(files[i]);
    }
    e.preventDefault();
}

ファイルアップロード部分

onprogressで進捗を把握できる。e.loadedはアップロードを行った容量で、e.totalは全体のアップロード容量である。

var request = new XMLHttpRequest();
request.upload.onprogress = function(e){
    document.getElementById('progress').style.width = ((e.loaded / e.total) * 100 + "%");
}

onload でアップロードの完了を取得できる。

request.upload.onload = function(e){
    document.getElementById('progress').style.width = '0px';
    alert('finished');
}
request.open('post', "./index.html");
request.send(files[i]);

Chromeについて

You can work around this by uploading the file via xmlhttprequest, maybe. I don’t
think Chrome has yet implemented the necessary HTML5 APIs for doing this yet,
unfortunately (they’re called FileStreams I think).

まだサポートしていないんじゃないか?と言ってるみたいだ。

WorkersからのDatabaseへのアクセスや,File API,XMLHttpRequestのFormData送信サポートなどはChrome 5での対応からChrome 6への対応に先送りされています

やっぱりFile APIへの対応はChrome6以降になったらしい。残念。

Web Platform Status

マイルストーン6で対応ですな=3

■サンプル

Firefox3.6以降でないと動かないですが、10MB以下のファイルを点線の中にドロップしてください。

You drop some files, here!

おまけ

jQuery1.4.2のbindを使うと、eventオブジェクトのプロパティdataTransferは、コールバック関数の引数のeventオブジェクトでは受け取れないようだ。従って、以下のコードは使えない。

$(elm).bind(
    'drop',
    function(e){
        e.preventDefault();
        var files = e.dataTransfer.files;
        for(var i = 0; i < files.length; i++){
            var request = new XMLHttpRequest();
            request.upload.onprogress = function(e){
                document.getElementById('progress').style.width = ((e.loaded / e.total) * 100 + "%");
            }
            request.upload.onload = function(e){
                document.getElementById('progress').style.width = '0px';
                alert('finished');
            }
            request.open('post', "./index.html");
            request.send(files[i]);
        }
        e.preventDefault();
    }
);

以下のようにaddEventListenerを使用すれば良い。

elm.addEventListener(
    'drop',
    function(e){
        e.preventDefault();
        var files = e.dataTransfer.files;
        for(var i = 0; i < files.length; i++){
            var request = new XMLHttpRequest();
            request.upload.onprogress = function(e){
                document.getElementById('progress').style.width = ((e.loaded / e.total) * 100 + "%");
            }
            request.upload.onload = function(e){
                document.getElementById('progress').style.width = '0px';
                alert('finished');
            }
            request.open('post', "./index.html");
            request.send(files[i]);
        }
        e.preventDefault();
    },
    false
);

さらにdropだけでなく、input type=”file”のchangeにもハンドリング可能だ。

elm.addEventListener(
    'change',
    function(e){
        e.preventDefault();
        var files = e.dataTransfer.files;
        for(var i = 0; i < files.length; i++){
            var request = new XMLHttpRequest();
            request.upload.onprogress = function(e){
                document.getElementById('progress').style.width = ((e.loaded / e.total) * 100 + "%");
            }
            request.upload.onload = function(e){
                document.getElementById('progress').style.width = '0px';
                alert('finished');
            }
            request.open('post', "./index.html");
            request.send(files[i]);
        }
        e.preventDefault();
    },
    false
);

3 Comments»

プログレスバーを参考にさせていただきました。

質問なのですがバイナリデータはsendでは送れないのでは?
自分も同じようなことをしているのですがFireFox限定のsendAsBinaryでないと無理でした。
どのようにして転送してるのでしょうか?

RSS feed for comments on this post.TrackBack URL

Leave a comment