Perlbalを使ったUploadプログレス表示
Webでファイルアップロードの仕組みって結構つかわれてますが、
大きなファイルをアップロードしている時、プログレスバーとかを
表示したかったりしますが、Perlbalでは簡単にできました。
Perlbalの設定ファイルには↓見たいに設定
肝は
CREATE SERVICE uptrack
と
SET upload_status_listeners = 127.0.0.1:7002, 10.54.0.1:7001
あとは普通のPerlbalの設定と同様
CREATE POOL nekokak_pool POOL nekokak_pool ADD 192.168.200.100:8000 CREATE SERVICE uptrack SET role = upload_tracker SET listen = 127.0.0.1:7002 ENABLE uptrack CREATE SERVICE nekokak SET role = reverse_proxy SET upload_status_listeners = 127.0.0.1:7002, 10.54.0.1:7001 SET pool = nekokak_pool ENABLE nekokak CREATE SERVICE http_server SET listen = 0.0.0.0:80 SET role = selector SET plugins = UrlGroup GROUP *.example.com = nekokak ENABLE http_server
ServerSideのプログラムは特にプログレス用の変更とかせずに
普通にファイルアップロードを処理するプログラムでおk
HTML側ではXmlHttpRequestを使うので大体↓見たいな感じになります
<div class="maincolumn"> <script> ////// public interface: function UploadTracker (formele, cb) { this.form = formele; this.callback = cb; this.session = UploadTracker._generateSession(); this.stopped = false; var action = this.form.action; if (action.match(/\bclient_up_sess=(\w+)/)) { action = action.replace(/\bclient_up_sess=(\w+)/, "client_up_sess=" + this.session); } else { action += (action.match(/\?/) ? "&" : "?"); action += "client_up_sess=" + this.session; } this.form.action = action; this._startCheckStatus(); } // method to stop tracking a form's upload status UploadTracker.prototype.stopTracking = function () { this.stopped = true; }; // private implementation details: UploadTracker._XTR = function () { var xtr; var ex; if (typeof(XMLHttpRequest) != "undefined") { xtr = new XMLHttpRequest(); } else { try { xtr = new ActiveXObject("Msxml2.XMLHTTP.4.0"); } catch (ex) { try { xtr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (ex) { } } } // let me explain this. Opera 8 does XMLHttpRequest, but not setRequestHeader. // no problem, we thought: we'll test for setRequestHeader and if it's not present // then fall back to the old behavior (treat it as not working). BUT --- IE6 won't // let you even test for setRequestHeader without throwing an exception (you need // to call .open on the .xtr first or something) try { if (xtr && ! xtr.setRequestHeader) xtr = null; } catch (ex) { } return xtr; }; UploadTracker._generateSession = function () { var str = Math.random() + ""; return curSession = str.replace(/[^\d]/, ""); }; UploadTracker.prototype._startCheckStatus = function () { var uptrack = this; if (uptrack.stopped) return true; var xtr = UploadTracker._XTR(); if (!xtr) return; var callback = function () { if (xtr.readyState != 4) return; if (uptrack.stopped) return; if (xtr.status == 200) { var val; eval("val = " + xtr.responseText + ";"); uptrack.callback(val); } setTimeout(function () { uptrack._startCheckStatus(); }, 1000); }; xtr.onreadystatechange = callback; xtr.open("GET", "/__upload_status?client_up_sess=" + uptrack.session + "&rand=" + Math.random()); xtr.send(null); } var uptrack; // our Perlbal upload tracker object, if defined // called from iframe's content on complete, with a URL of where we should go: function onUploadComplete (destURL) { window.location = destURL; } // called by the perlbal upload tracker library: (we pass it this function below) function uploadCallback (data) { if (! (data && data.total)) return; var percent = Math.floor(data.done * 100 / data.total); document.getElementById("UploadBarInside").style.width = percent + "%"; var status = Math.floor(data.done / 1024) + " kB / " + Math.floor(data.total / 1024) + " kB, " + percent + "% complete"; document.getElementById("UploadStatus").innerHTML = status; } function submitForm () { if (uptrack) uptrack.stopTracking(); var frm = document.getElementById("WebUpload"); frm.target = "upiframe"; // change target to our iframe // create the actual Perlbal upload tracker object: uptrack = new UploadTracker(frm, uploadCallback); document.getElementById("UploadStatus").innerHTML = "Uploading, please wait..."; document.getElementById("UploadBar").style.display = "block"; return true; } </script> <iframe name="upiframe" id="upiframe" height="0" width="0"> </iframe> <div name="UploadBarInside" id="UploadBarInside"></div> <div name="UploadStatus" id="UploadStatus"></div> <div name="UploadBar" id="UploadBar"></div> <form action="/upload/" method="post" name="WebUpload" id="WebUpload" enctype="multipart/form-data" onSubmit="submitForm()"> <input name="file" type="file" /> <input name="upload" type="submit" /> </form> </div>
これで、ファイルをアップロードすると、プログレスが表示されます。
もう少し手を加えればもとおされにプログレス表示したりもできますね。
こういうのはサンプルのサイトがあったほうがいいなぁ。
来週の時間のあるときにでも用意するかもです。