nginx_uploadprogress_module - upstreamサーバに転送する時に RFC1867 POST アップロードを監視する、アップロード進捗システムの実装です。
アップロードされた内容を解析すること無しに、NGINXによってupstreamサーバにプロキシされるアップロードを追跡することで動作し、JavaScript、JSON、あるいは設定可能な形式でアップロードの進捗を報告するweb APIを提供します。NGINXはアップロードされたPOSTの内容をupstreamサーバに転送する前にディスクに格納し、upstreamサーバのアクセラレータとして振舞うため、このように動作します。個々の各POSTアップロードリクエストは進捗のユニークな識別子を持つべきです。
JSONと仕組みの考えは、Lighttpd の mod_uploadprogressに基づいています。
注意
このモジュールはNGINXのソースと一緒に配布されません。
masterzen/nginx-upload-progress-module
警告
バージョン 0.9.0 では、非互換の変更があります: JSONPは今では進捗の調査のデフォルトの出力です。もし、以下のように非推奨のjava出力を提供するこのモジュールに頼る場合は:
upload_progress_java_output
進捗調査locationの中で。
解凍した後で、以下のオプションをNGINX ./configure
コマンドに追加します。
--add-module=path/to/nginx_uploadprogress_module
警告
--with-debug
を使ってコンパイルされた場合、このモジュールはかなり多くのログメッセージを生成するでしょう。
構文: | upload_progress |
---|---|
デフォルト: | n/a |
コンテキスト: | http |
このディレクティブはアップロード進捗モジュールを有効にし、接続ごとの追跡情報を格納するために使われるzone_nameにzone_size バイトを予約します。
構文: | track_uploads |
---|---|
デフォルト: | n/a |
コンテキスト: | 場所 |
このディレクティブは現在のlocationのためのアップロードの追跡を有効にします。このlocationへのPOSTの到着はzone_name アップロード進捗トラッカー内にリクエストを登録するでしょう。NGINXはまだ RFC 1867 アップロードをサポートしないため、locationは proxy_pass あるいは fastcgi location でなければなりません。POSTは、進捗情報を取得するために使われるユニークな識別子を値に持つX-Progress-IDと呼ばれるクエリパラメータ (あるいは同じ名前の HTTP ヘッダ)を持たなければなりません。POSTがそのような情報を持たない場合、アップロードは追跡されないでしょう。The tracked connections are kept at most timeout seconds after they have been finished to be able to serve unseful information to upload progress probes.
警告
このディレクティブはlocationの最後のディレクティブでなければなりません。proxy_pass あるいは fastcgi_pass locationの中になければなりません。location内でのディレクティブの繰り返しはsegfaultsに繋がるでしょう。
構文: | report_uploads |
---|---|
デフォルト: | n/a |
コンテキスト: | 場所 |
このディレクティブによりlocationはzone_nameについて track_uploadsによって追跡されるアップロード進捗を報告することができます。返されるドキュメントはデフォルトで4つの結果を取り得るJavascriptテキストです:
アップロードリクエストはまだ登録されていないか、unknownです:
new Object({ 'state' : 'starting' })
アップロードリクエストが終了しました:
new Object({ 'state' : 'done' })
アップロードリクエストがHTTPエラーを起こしました
new Object({ 'state' : 'error', 'status' : <error code> })
クライアントのために追跡に使うことができる1つのエラーコードが 413 (request entity too large) です。
アップロードリクエストは進行中です:
new Object({ 'state' : 'uploading', 'received' : <size_received>, 'size' : <total_size>})
このjavascriptの代わりにピュアなjsonを返すことができます (upload_progress_json_outputを見てください)。upload_progress_templateディレクティブを使って応答フォーマットを完全に設定することも可能です。
このlocationへのHTTPリクエストはX-Progress-IDパラメータを持つか、進捗中のアップロードの有効なユニークな識別子が含まれるHTTPヘッダを持つ必要があります。
構文: | upload_progress_content_type |
---|---|
デフォルト: | test/javascript |
コンテキスト: | 場所 |
このディレクティブを使ってアップロード進捗調査content-typeを変更することができます。
構文: | upload_progress_header |
---|---|
デフォルト: | X-Progress-ID |
コンテキスト: | 場所 |
このディレクティブを使って進捗IDのヘッダー名を変更することができます。
構文: | upload_progress_jsonp_parameter |
---|---|
デフォルト: | callback |
コンテキスト: | 場所 |
このディレクティブを使って、jsonpコールバック名を持つGETパラメータの名前を変更することができます。
構文: | upload_progress_json_output |
---|---|
デフォルト: | n/a |
コンテキスト: | main,sever,location |
このディレクティブはピュアなjsonとして全てを出力するように設定します。
構文: | upload_progress_jsonp_output |
---|---|
デフォルト: | none |
コンテキスト: | 場所 |
このディレクティブはjsonpとして全てを出力するように設定します(json出力だがcallbackをf持たない)。
構文: | upload_progress_template |
---|---|
デフォルト: | n/a |
コンテキスト: | 場所 |
このディレクティブは進捗応答テンプレートをインストールするために使うことができます。利用可能な状態のリスト:
NGINXは以下の変数の値をアップロードについてのそれぞれの値に置き換えるでしょう:
例えば、(デフォルトのJavascriptあるいはjsonの代わりに)XMLを返すには:
upload_progress_content_type 'text/xml';
upload_progress_template starting '<upload><state>starting</state></upload>';
upload_progress_template uploading '<upload><state>uploading</state>
<size>$uploadprogress_length</size><uploaded>$uploadprogress_received</uploaded></upload>';
upload_progress_template done '<upload><state>done</state></upload>';
upload_progress_template error '<upload><state>error</state>
<syntaxhighlight>$uploadprogress_status</syntaxhighlight></upload>';
jsonp応答の例:
upload_progress_template starting "$uploadprogress_callback({ 'state' : 'starting'});";
upload_progress_template error "$uploadprogress_callback({ 'state' : 'error',
'status' : $uploadprogress_status });";
upload_progress_template done "$uploadprogress_callback({ 'state' : 'done'});";
upload_progress_template uploading "$uploadprogress_callback({ 'state' : 'uploading',
'received' : $uploadprogress_received, 'size' : $uploadprogress_length });";
http {
# reserve 1MB under the name 'proxied' to track uploads
upload_progress proxied 1m;
server {
listen 127.0.0.1 default;
server_name localhost;
root /path/to/root;
location / {
# proxy to upstream server
proxy_pass http://127.0.0.1;
proxy_redirect default;
# track uploads in the 'proxied' zone
# remember connections for 30s after they finished
track_uploads proxied 30s;
}
location ^~ /progress {
# report uploads tracked in the 'proxied' zone
report_uploads proxied;
}
}
}
(Lighttd mod_uploadprogress もジュールの例に基づいています):
まず、アップロードフォームが必要です:
<form id="upload" enctype="multipart/form-data"
action="/upload.php" method="post" onsubmit="openProgressBar(); return true;">
<input type="hidden" name="MAX_FILE_SIZE" value="30000000" />
<input name="userfile" type="file" label="fileupload" />
<input type="submit" value="Send File" />
</form>
進捗を表示するための進捗バー:
<div>
<div id="progress" style="width: 400px; border: 1px solid black">
<div id="progressbar" style="width: 1px; background-color: black; border: 1px solid white"> </div>
</div>
<div id="tp">(progress)</div>
</div>
そして、ユニークな識別子を生成し、submitアクション上でアップロードを起動する必要があります。これはajax進捗レポート機構も開始するでしょう。
interval = null;
function openProgressBar() {
/* generate random progress-id */
uuid = "";
for (i = 0; i < 32; i++) {
uuid += Math.floor(Math.random() * 16).toString(16);
}
/* patch the form-action tag to include the progress-id */
document.getElementById("upload").action="/upload.php?X-Progress-ID=" + uuid;
/* call the progress-updater every 1000ms */
interval = window.setInterval(
function () {
fetch(uuid);
},
1000
);
}
function fetch(uuid) {
req = new XMLHttpRequest();
req.open("GET", "/progress", 1);
req.setRequestHeader("X-Progress-ID", uuid);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
/* poor-man JSON parser */
var upload = eval(req.responseText);
document.getElementById('tp').innerHTML = upload.state;
/* change the width if the inner progress-bar */
if (upload.state == 'done' || upload.state == 'uploading') {
bar = document.getElementById('progressbar');
w = 400 * upload.received / upload.size;
bar.style.width = w + 'px';
}
/* we are done, stop the interval */
if (upload.state == 'done') {
window.clearTimeout(interval);
}
}
}
}
req.send(null);
}
NGINX upload-progress-module と一緒にjQueryプラグインを使うことができます - https://github.com/drogus/jquery-upload-progress (そのドキュメントに基づいています)。
htmlの一部:
<form id="upload" enctype="multipart/form-data" action="index.html" method="post">
<input name="file" type="file"/>
<input type="submit" value="Upload"/>
</form>
<div id="uploading">
<div id="progress" class="bar">
<div id="progressbar"> </div>
<div id="percents"></div>
</div>
</div>
cssの一部:
.bar {
width: 300px;
}
#progress {
background: #eee;
border: 1px solid #222;
margin-top: 20px;
}
#progressbar {
width: 0px;
height: 24px;
background: #333;
}
少しのjavascript
$(function() {
$('form').uploadProgress({
/* scripts locations for safari */
jqueryPath: "../lib/jquery.js",
uploadProgressPath: "../jquery.uploadProgress.js",
/* function called each time bar is updated */
uploading: function(upload) {$('#percents').html(upload.percents+'%');},
/* selector or element that will be updated */
progressBar: "#progressbar",
/* progress reports url */
progressUrl: "/progress",
/* how often will bar be updated */
interval: 2000
});
});
アップロードサーバが通常のwebサーバと違う場合など、異なるドメインあるいはサブドメイン(クロスドメイン)から進捗バーを更新する必要がある場合は、以下のようにJSONPプロトコルを試すことができます:
$(function() {
$('form').uploadProgress({
/* scripts locations for safari */
jqueryPath: "../lib/jquery.js",
uploadProgressPath: "../jquery.uploadProgress.js",
/* function called each time bar is updated */
uploading: function(upload) {$('#percents').html(upload.percents+'%');},
/* selector or element that will be updated */
progressBar: "#progressbar",
/* progress reports url in a different domain or subdomain from caller */
progressUrl: "uploads.somewhere.com/progress",
/* how often will bar be updated */
interval: 2000,
/* use json-p for cross-domain call */
dataType: 'jsonp'
});
});
デフォルト:
このソフトウェアは Valery Kholodkov の NGINX アップロードモジュールとも動作します: http://www.grid.net.ru/nginx/upload.en.html