それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

File APIその後使ってみて

ファイルAPIをその後ちょっと使う機会があった。いくつか気づいたことがあったのでメモ

The File object provides information about -- and access to the contents of -- files. These are generally retrieved from a FileList object returned as a result of a user selecting files using the input element, or from a drag and drop operation's DataTransfer object.

input type file以外でもファイルは取れるが

  • ドラッグ&ドロップは DataTransfer オブジェクト経由
  • XmlHttp は BlobBuilder 経由
  • data Schema は Blob 経由

でそれぞれファイルを扱うのに、同じことができる。

input[type=file]と微妙に扱いが違うみたいなのが気になった。

それぞれの受け取り方

blob の場合は onload 待ちをしないとサイズが取れない

たとえば、画像のサイズを取得するには。

data schemeの場合

            main_img.src = "data:image/jpeg;base64,"+v
            main_img.onload = function(){
                actual1 = getActualDimension( main_img )
                main_img.width = actual1.width;
                main_img.height = actual1.height         
                window.img_history.push(new HistoryObject(main_img.src))
                
              }

dataTransferの場合

        var dt = event.dataTransfer;
        var file = dt.files[0];
        window.img_file = file
        var url = window.URL.createObjectURL(file)
        main_img.src = url
        main_img.onload = function(){
          actual1 = getActualDimension( main_img )
          main_img.width = actual1.width;
          main_img.height = actual1.height          
        }
一番のベターな手法やっぱりreader

data の場合は、Readerで待つ

        var dt = event.dataTransfer;
        var file = dt.files[0];
        var reader = new FileReader();
        reader.onload = (function(img) { return function(e) {
              img.src = e.target.result;
              actual1 = getActualDimension( img )
              img.width = actual1.width;
              img.height = actual1.height
           }; })(main_img);
        reader.readAsDataURL(file);

ファイルをそのまま、POSTするのにはAjaxではちょっとコツが居る

Ajaxは form-enclosed を渡す(GET引数と同等のものをリクエスト本文に入れる)だけしか基本はできない。multipart/formdataを送ることは出来ない。

formdataをつかえば送ることが出来る

もちろんファイルアップロード(multipart/formdata)をXmlHTTPで送ることが出来る
それがformdata オブジェクト

      var fd = new FormData()
      fd.append("img",file)
      fd.append("geometry.x",$("#selection").get(0).offsetLeft)
      fd.append("geometry.y",$("#selection").get(0).offsetTop)
      fd.append("geometry.w",$("#selection").width() )
      fd.append("geometry.h",$("#selection").height() )

jQueryから使うには更に特殊

jqueryでは、自動的に変数展開をするので、それをオフにする必要がある。つまり

formdata は processdata と contenttypeがfalse必須

コードでかくと。。。

$.ajax({ 
           type:"post",
           url:"./test",
           data:fd,//formdataのオブジェクト 
           contentType: false,
           processData: false

}).done(function( msg ) { console.log( "Data Saved: " + msg ); });

のように、事前処理をオフにしないと、jQueryAjaxでファイルをアップロードすることは出来ない。
とりあえず、2012-08-5現在の仕様だった。

このへんはどんどん変わるので、正直言えばもう少し安定してから使いたい。

ちなみに実験環境はChrome(Webkit)


iOS6からファイルをアップロードが可能になるので、このへんはどんどん使われて、もっと良いやり方が出てきてくれると助かる。とくにjQuery周りはもうちょっと改善されると嬉しい。jQuery.Ajax.fileupload的なものが欲しいです。