Mach3.laBlog

“FormData” – Alphabetical Advent Calendar 2013

この記事は賞味期限切れです。(更新から1年が経過しています)

“F” は FormData の “F”。

F

FormData

FormData は XMLHttpRequest Level 2 で新たにサポートされるオブジェクトで、Ajaxでの値の送信をより簡単な物にしてくれます。

FormData – Web API リファレンス | MDN

XMLHttpRequest Level 2 は新たに FormData インタフェースのサポートを追加します。FormData オブジェクトは、XMLHttpRequest の send() メソッドを用いることで簡単に送信が可能な、フォームフィールドおよびそれらの値から表現されるキーと値のペアのセットを簡単に構築する手段を提供します。

使い方は至って簡単で、new で生成して append メソッドでキーと値を登録するだけです。 値をセットした FormData オブジェクトは、XMLHttpRequest オブジェクトの send メソッドにそのまま渡せます。

var data = new FormData();
data.append("name", "john");
data.append("email", "john@example.com");

var xhr = new XMLHttpRequest();
xhr.open("POST", "send.php");
xhr.send(data);

form エレメントを渡して初期化する事もできます。そこに append で値を追加する事もできます。

var form = document.getElementById("myform");
var data = new FormData(form);
data.append("age", 18);

FormData でファイルの送信をする

FormData の嬉しい所は、Ajaxによるファイルの送信が非常に簡潔に書ける点です。 File API をサポートしている環境ならば、append の値に File オブジェクトを渡すことが出来るので、 非常に直感的なコードになりますね。 (FormDataをサポートしていてFile APIをサポートしていない環境があるのかどうかは分かりませんが)

ドラッグドロップからの送信

先日書いたようなドラッグドロップを利用して、ページにドロップされたファイルを即時にAjaxでサーバーに送ってみるシンプルな例です。 このコードは FormData も File API もサポートしている環境を前提としています。

※簡易化の為、XHR以外の部分は jQuery を使って記述しています。

$(window).on("dragover drop", function(e){
    e.preventDefault();
});

$(document).on("drop", function(e){
    var files = e.originalEvent.dataTransfer.files;
    var data = new FormData();
    $.each(files, function(i, file){
        data.append("userfile[]", file);
    });

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "send.php");
    xhr.addEventListener("readystatechange", function(e){ ... }, false);
    xhr.send(data);
});

input[type=file] からの送信

ドラッグドロップではなく、フォームエレメントで選択されたファイルを送信してみた例です。 input[type=file] は、 files という名前で FileList を属性に持っているのでそれを参照します。

$("#form-test").on("submit", function(e){
    e.preventDefault();
    var data = new FormData();
    var files = $("input[name=userfile]")[0].files;
    $.each(files, function(i, file){
        data.append("userfile[]", file);
    });

    // あとは前項と共通
});

FormData が使えない場合のファイルアップロード

FormData が使えない環境でXHRを使用したファイルのアップロードを実装する為には、 Ajaxリクエストの内容を自前でゴリゴリ書いていく必要があります。

Javascript: Uploading a file… without a file – Stack Overflow

上記URLの回答のコードの抜粋です。

function beginQuoteFileUnquoteUpload(data)
{
    // Define a boundary, I stole this from IE but you can use any string AFAIK
    var boundary = "---------------------------7da24f2e50046";
    var xhr = new XMLHttpRequest();
    var body = '--' + boundary + '\r\n'
             // Parameter name is "file" and local filename is "temp.txt"
             + 'Content-Disposition: form-data; name="file";'
             + 'filename="temp.txt"\r\n'
             // Add the file's mime-type
             + 'Content-type: plain/text\r\n\r\n'
             + data + '\r\n'
             + boundary + '--';

    xhr.open("POST", "http://www.mysite.com/myuploadhandler.php", true);
    xhr.setRequestHeader(
        "Content-type", "multipart/form-data; boundary="+boundary
    );
    xhr.onreadystatechange = function ()
    {
        if (xhr.readyState == 4 && xhr.status == 200)
            alert("File uploaded!");
    }
    xhr.send(body);
}

application/x-www-form-urlencoded だともう少し短いコードになっていましたが(引用元参照)、 multipart/form-data を Ajax で送るのはかなり手間がかかる様ですね。 要するに FormData がその辺を全てやってくれているわけで、大変有難いです。

参考資料

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*