ファイル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 ); });
のように、事前処理をオフにしないと、jQueryのAjaxでファイルをアップロードすることは出来ない。
とりあえず、2012-08-5現在の仕様だった。
このへんはどんどん変わるので、正直言えばもう少し安定してから使いたい。
iOS6からファイルをアップロードが可能になるので、このへんはどんどん使われて、もっと良いやり方が出てきてくれると助かる。とくにjQuery周りはもうちょっと改善されると嬉しい。jQuery.Ajax.fileupload的なものが欲しいです。