速度制限が毎日続くTakuyaです。こんにちは!。
データセンターにmpeg動画を送信して、サーバー側でffmpeg 掛けてました。節電の為に自宅鯖を停止し、Linuxボックスだけ起動してました。重い処理はサーバーにやらせてました。ファイル送信が3TB超えてついに速度制限を喰らいました。怖いですね。11/01に無事解除されましたが。。。
<input type=file /> の通信状況を見たい。
UP速度制限が100kbpsでした、ブラウザのファイルアップロードに不自由を感じました。iphone4の写真UPに1枚あたり30秒位かかってました。さくらVPSのWEBアプリに写真をアップするだけでも大変でした。ファイル送信状況が見えないと不安しかたありません。< input type=file/> でアップしたファイルの送信状況を見れるようにフォームを改造しました。
送信状況のプログレスバーを作るには?
- ajax で送信する
- XmlHttpの progress イベントを使う。
この2つを満します。ファイルアップロードを作ることが出来ました。
ajax で送信する
ajax の ansychronous モードは必須です。async=trueで送れば、進捗が見られました。syncモード(async=false)では状況モニタリング出来ませんでした。。*1
progressイベントを使う
progressイベントのハンドラを登録すると使えます。つかいかたは、Mozillaのページが分かりやすい。
var req = new XMLHttpRequest(); req.addEventListener("progress", updateProgress, false); req.addEventListener("load", transferComplete, false); req.addEventListener("error", transferFailed, false); req.addEventListener("abort", transferCanceled, false); req.open();https://developer.mozilla.org/ja/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest:
コールバック関数で アップしたファイルサイズを見る
function updateProgress(evt) { var percentComplete = evt.loaded / evt.total; }
- event.total
- アップ中ファイルのトータルサイズ
- event.loaded
- アップしたファイルサイズ
loaded とあるがこれが送信済みファイルサイズ。
jQueryでやりたい。
Ajaxを生でやるより、$.ajaxを使いたいですよね。わかります。僕もです。
xmlhttpを直接触るのは控えたい。jQueryを導入してるので jQueryでやりたい。
jqueryの$.jajaxに progressを使う
var start_upload = function(){ $.each( files_field.files, function(i,e){ var fd = new FormData(); fd.append("filename", e ); fd.append("dummy", "1234" ); $.ajax({ async: true, xhr : function(){ XHR = $.ajaxSettings.xhr(); if(XHR.upload){ XHR.upload.addEventListener('progress',function(e){ progre = parseInt(e.loaded/e.total*10000)/100 ; console.log(progre+"%") ; $("#progress_bar").width(parseInt(progre/100*300*100)/100+"px"); $("#progress_bar").height("30px"); $("#progress_bar").html(progre+"%"); }, false); } return XHR; }, url: "/test/", type: "post", data:fd,//formdataのオブジェクト contentType: false, processData: false }).done(function( msg ) { console.log( msg );$("#output").append(msg) }); } ) }
出来上がりは上記のようになりました。
FileAPIとProgressを使ってる2箇所について抜き出して解説します。
大事な所:1
$.ajaxでプログレスイベントを拾う箇所
$.ajax({ async: true, xhr : function(){ XHR = $.ajaxSettings.xhr(); XHR.upload.addEventListener('progress',function(e){}) return XHR; }, type: "post", data:fd,//formdataのオブジェクト contentType: false, processData: false });
jqueryの $.ajax引数に { xhr:function(){} } を渡します。これが生の XHR書換えるの基本だと思います。
大事な箇所:2
$.ajaxでファイルをアップロードする ( multipart/form-dataを ajaxで送る )
jQueryでファイルアップロードには、手順が必要です
var fd = new FormData(); fd.append( $(":file").get(0).files.item(0), e ); $.ajax({ type: "post", data:fd,//formdataのオブジェクト contentType: false, processData: false });
詳しくは以前のエントリに→File APIその後使ってみて - ブックマクロ開発に
jquery特徴
<inpu type=file multiple=multiple>で複数ファイルを取得するには、次のようにします。
$.map( $(":file").get(0).files, function(e,i ){ console.log(e); return e })
最後に
jqueryを使わず、純粋にファイルの送信状況を出す部分
var req = new XMLHttpRequest(); req.upload.onprogress =function(e){ console.log((e.loaded / e.total) * 100 + "%"); } req.open("POST", "/test/" ); req.send( e );
簡単ですね。websocketでやるのかなとおもったら xmlhttpに組み込まれてて安心した。