nginx上傳模塊nginx_upload_module和nginx_uploadprogress_module模塊進度顯示,如何傳遞GET參數等。
ownload:
http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
configure and make :
- ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/data/software/lnmp1.1-full/nginx_http_push_module-0.73 --add-module=/data/software/lnmp1.1-full/ngx_cache_purge-2.1 --add-module=/data/software/lnmp1.1-full/nginx_upload_module-2.2.0
Nginx配置文件:
較靠譜的文章:http://blog.sina.com.cn/s/blog_704836f401014bpj.html
<?php
$temppath = $_POST["file1_path"];
$name = $_POST["file1_name"];
$md5 = $_POST["file1_md5"];
$f_dir = substr($md5,0,1);
$s_dir = substr($md5,-1);
$final_file_path = "/".$f_dir."/".$s_dir."/".$name;
echo $temppath."<br />";
echo $name."<br />";
echo $md5."<br />";
echo $f_dir."<br />";
echo $s_dir."<br />";
echo $final_file_path;
rename($temppath,$final_file_path);
?>
因為nginx upload module已經做完了最費時的mime解析工作,后端的PHP代碼只需要簡單的移動文件到合適的位置就可以了。因為upload module是使用C語言寫的,比起PHP作解析工作的效率高多了,因此極大地提高了文件上傳的效率。
二、upload module的配置參數簡要說明
下邊是一些配置參數的說明:
upload_pass 指明了需要后續處理的php地址
upload_cleanup 如果php出現400 404 499 500-505之類的錯誤,則刪除上傳的文件
upload_store 上傳文件存放地址
upload_store_access 上傳文件的訪問權限,user:r是指用戶可讀
upload_limit_rate 上傳限速,如果設置為0則表示不限制
upload_pass_form_field 從表單原樣轉到后端的參數,可以正則表達式表示
官方的例子是upload_pass_form_field "^submit$|^description$";
意思是把submit,description這兩個字段也原樣通過upload_pass傳遞到后端php處理。如果希望把所有的表單字段都傳給后端可以用upload_pass_form_field "^.*$";
---------------
背景:追求極致,由服務器腳本(比如PHP)來負責接收上傳的數據。這種方式存在性能和效率的問題。所以,決定采用Nginx的上傳模塊來完成接收數據的功能,接收完數據后,再去轉給后端腳本語言進行后續處理(比如:移動文件、插入文件的信息到數據庫中)。
RFC 1867:
module for nginx web server for handling file uploads using multipart/form-data encoding (RFC 1867) and resumable uploads according to this protocol.
Description
The module parses request body storing all files being uploaded to a directory specified by upload_store directive. The files are then being stripped from body and altered request is then passed to a location specified by upload_pass directive, thus allowing arbitrary handling of uploaded files. Each of file fields are being replaced by a set of fields specified by upload_set_form_field directive. The content of each uploaded file then could be read from a file specified by $upload_tmp_path variable or the file could be simply moved to ultimate destination. Removal of output files is controlled by directive upload_cleanup. If a request has a method other than POST, the module returns error 405 (Method not allowed). Requests with such methods could be processed in alternative location via error_page directive.
Nginx.conf
======================================================================
- user www www;
- worker_processes 5;
- error_log /data1/logs/nginx_error.log crit;
- pid /usr/local/webserver/nginx/nginx.pid;
- #Specifies the value for maximum file descriptors that can be opened by this process.
- worker_rlimit_nofile 51200;
- events
- {
- use epoll;
- worker_connections 51200;
- }
- http
- {
- include mime.types;
- default_type application/octet-stream;
- #charset gb2312;
- server_names_hash_bucket_size 128;
- client_header_buffer_size 32k;
- large_client_header_buffers 4 32k;
- client_max_body_size 8m;
- sendfile on;
- tcp_nopush on;
- keepalive_timeout 60;
- tcp_nodelay on;
- fastcgi_connect_timeout 300;
- fastcgi_send_timeout 300;
- fastcgi_read_timeout 300;
- fastcgi_buffer_size 64k;
- fastcgi_buffers 4 64k;
- fastcgi_busy_buffers_size 128k;
- fastcgi_temp_file_write_size 128k;
- gzip on;
- gzip_min_length 1k;
- gzip_buffers 4 16k;
- gzip_http_version 1.0;
- gzip_comp_level 2;
- gzip_types text/plain application/x-javascript text/css application/xml;
- gzip_vary on;
- server
- {
- listen 80;
- server_name test.local;
- index index.php index.shtml index.htm index.html;
- root /data/app/test.local/wwwroot;
- access_log off;
- location /upload {
- upload_pass /index.php?c=uploader&a=upload_server;
- upload_cleanup 400 404 499 500-505;
- upload_store /data/app/test.local/upload_tmp;
- upload_store_access user:r;
- upload_limit_rate 128k;
- upload_set_form_field "${upload_field_name}_name" $upload_file_name;
- upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
- upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;
- upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
- upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;
- upload_pass_form_field "^.*$";
- }
- location ~ .*\.php?$
- {
- #include fastcgi_params;
- fastcgi_pass 127.0.0.1:9000;
- fastcgi_index index.php;
- include fcgi.conf;
- }
- location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
- expires 30d;
- }
- location ~ .*\.(js|css)?$ {
- expires 1d;
- }
- }
- }
1.上面的#include fastcgi_params; 被我注釋掉了,否則出現:405 Method not allowed ,查了下:
Nginx 靜態文件中的 POST 請求返還 405 Method not allowed 錯誤,于是用了9000的PHP端口。
index.php 內容:
- <?php
- print_r($_POST);
- echo $upload_tmp_path;
- $temppath = $_POST["file1_path"];
- $name = $_POST["file1_name"];
- $md5 = $_POST["file1_md5"];
- $f_dir = substr($md5,0,1);
- $s_dir = substr($md5,-1);
- $final_file_path = "/".$f_dir."/".$s_dir."/".$name;
- echo $temppath."<br />";
- echo $name."<br />";
- echo $md5."<br />";
- echo $f_dir."<br />";
- echo $s_dir."<br />";
- echo $final_file_path;
- rename($temppath,$final_file_path);
- ?>
上傳后返回:
Array
(
[file1_name] => 6597350142123536341.jpg
[file1_content_type] => image/jpeg
[file1_path] => /data/app/test.local/upload_tmp/0000000001
[file1_md5] => 5a84d879e497bf64acebdc84c4701a76
[file1_size] => 110001
[file2] =>
[file3] =>
[file4] =>
[file5] =>
[file6] =>
[submit] => Upload
[test] => value
)
先看一下這個上傳目錄的結構是這樣的,這些編號的都是上傳的素材,沒有后綴:
/data/app/test.local/upload_tmp# ls
0000000001 0006630963 0006630964
查看目錄下有沒有這個文件:
ls /data/app/test.local/upload_tmp/0000000001
/data/app/test.local/upload_tmp/0000000001
sz 下來,更名為.jpg的:
sz /data/app/test.local/upload_tmp/0000000001 ==》0000000001.jpg ,打開一看果然是我上傳的文件,得證!
把這個文件放到自己定義的目錄下:
- <?php
- $temppath = $_POST["file1_path"];
- $name = $_POST["file1_name"];
- $orgFileName = "/data1/files/".$name;
- rename($temppath,$orgFileName);
- ?>
多個文件的一個情況,也就是多個文件的POST數組規律,去進行移動文件即可:
<input type="file" name="file2">
<input type="file" name="file2">
[file1_name] => 1332460275090024.jpg
[file1_content_type] => image/jpeg
[file1_path] => /data/app/test.local/upload_tmp/0000000034
[file1_md5] => 4e84aac3bc2cc25b7c69c7b506e4967f
[file1_size] => 73702
[file2_name] => desktop.ini
[file2_content_type] => application/octet-stream
[file2_path] => /data/app/test.local/upload_tmp/0000000035
[file2_md5] => dc723b859dec1526568ad581aec334d5
因為nginx upload module已經做完了最費時的mime解析工作,后端的PHP代碼只需要簡單的移動文件到合適的位置就可以了。因為upload module是使用C語言寫的,比起PHP作解析工作的效率高多了,因此極大地提高了文件上傳的效率。
upload_cleanup 如果php出現400 404 499 500-505之類的錯誤,則刪除上傳的文件,這塊可以利用PHP進行邏輯判斷后輸出header頭來進行操作是否刪除文件。
======================================================================
補安裝編譯方法:
1.下載
wget http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
2.編譯(在NGINX編譯目錄執行以下命令, 其中 --add-module=你下載解壓的上傳插件目錄)
./configure --user=www --group=www --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/root/software/nginx_http_push_module-0.692 --add-module=/root/software/ngx_cache_purge-1.3 --add-module=/root/software/nginx_upload_module-2.2.0
3.上傳界面:
參考來源:
1)nginx上傳模塊—nginx upload module安裝:http://waynerqiu.com/7/136.html
2)寫得很簡潔的安裝方法:http://foooy.me/nginx/158.html 【該文里提到的接受PHP,這塊沒有做詳細的配置,參考上面這篇文章即可。】
3)http://anerg.com/read.php?55
//這一篇文章描述到:upload_pass /index.php?c=uploader&a=upload_server; 也就是有框架時怎么用框架的action來進行處理。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
最后,后記備查用相關模塊的使用:
聽說有一個哥們解決了get的問題,通過相關nginx的指令實現的,沒實踐:http://waynerqiu.com/7/139.html
還有實現斷點續傳,進度顯示等的:
最近做一個產品,需要實現從網頁上傳文件給服務器。一般情況下都是采用Ajax異步方式,創建一個iframe,在iframe里面把數據以form方式提交給后端的服務器腳本,由服務器腳本(比如PHP)來負責接收上傳的數據。這種方式存在性能和效率的問題。所以,決定采用Nginx的上傳模塊來完成接收數據的功能,接收完數據后,再去轉給后端腳本語言進行后續處理(比如:移動文件、插入文件的信息到數據庫中)。同時,由于需要在前端展現上傳的進度,因此可以利用Nginx一個uploadprogress模塊來獲取。
整個處理框圖如下:
實現步驟:
1、查看Nginx是否安裝了這兩個模塊(nginx_upload_module和nginx_uploadprogress_module),命令nginx -V (注意是大寫),可以查看Nginx當時編譯時候的參數,如果發現有上述兩個模塊,說明Nginx已經安裝了這兩個模塊。如果沒有的話,就需要安裝這兩個Nginx模塊。由于這兩個模塊不在Nginx源代碼中,需要重新編譯Nginx,在編譯選項中加上
--add-module=/模塊源代碼路徑/nginx_upload_module-2.2.0 --add-module=/模塊源代碼路徑/nginx_uploadprogress_module-0.8.2 。
2、由于產品的前端使用的是jQuery框架,所以,找了一個現成的jQuery下的上傳文件插件(ajaxfileupload)。該代碼基本原理就是動態創建一個iframe,在iframe中再增加一個form,最后數據放到這個form中提交給服務器,代碼量比較小也就200來行代碼。前端的代碼如下:
- <script type="text/javascript" src="http://192.168.1.203:7100/js/libs/ajaxfileupload.js" ></script>
- <script type="text/javascript">
- function uploadfile(){
- $.ajaxFileUpload({
- url:'http://192.168.1.203:7100/upload/‘,//上傳的地址
- sercureuri:false,
- fileElementId:'fileToUpload',
- dataType:'json',
- success:function(data,status){
- if(typeof(data.error) != 'undefined'){
- if(data.error != '')
- alert(data.error);
- }
- else{
- alert(data.msg);
- }
- },
- error:function(data,status, e){
- alert(e);
- }
- });
- return false;
- }
- </script>
- <div>
- <input type="file" name="addfile" size="50" id="fileToUpload" />
- <input type="button" value="上傳" onclick="return uploadfile();"/>
- </div>
其中,success的回調函數參數是服務器返給瀏覽器的結果。
3、配置Nginx,實現上傳模塊來接收頁面上傳的文件。把下面配置添加到Nginx的配置文件中,注意是加在server的上下文中。
location = /upload {
upload_pass /service.php?path=uploadfile&a=upload_server;//表示Nginx接收完上傳的文件后,然后交給后端處理的地址
upload_cleanup 400 404 499 500-505; //表示當發生這些http status代碼的情況下,會把上傳的文件刪除
upload_store /tmp/upload_tmp 1;//上傳模塊接收到的文件臨時存放的路徑, 1 表示方式,該方式是需要在/tmp/upload_tmp下創建以0到9為目錄名稱的目錄,上傳時候會進行一個散列處理。
upload_store_access user:r; //指定訪問模式
upload_limit_rate 128k; //設定上傳速度上限
upload_set_form_field "${upload_field_name}_name" $upload_file_name; //設定后續腳本語言訪問的變量,其中${upload_field_name}對照本例子就是addfile。比如后臺PHP就可以通過$_POST['addfile_name']來獲取上傳文件的名稱。
upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;//同上
upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;//由于在upload_store設置了臨時文件存放根路徑,該路徑就是經過散裂后上傳文件存在真實路徑,比如后續處理可以根據這值把上傳文件拷貝或者移動到指定的目錄下。
upload_pass_form_field "^.*$";//
upload_pass_args on;// 打開開關,意思就是把前端腳本請求的參數會傳給后端的腳本語言,比如:http://192.168.1.203:7100/upload/?k=23.PHP腳本可以通過$_POST['k']來訪問。
}
4、上述配置完了,就可以實現上傳的功能了。但是,要獲取上傳的進度,那還是需要配置另外一個模塊nginx_uploadprogress_module。其實,獲取當前進度原理比較簡單,就是通過javascript以異步方式定時給特定地址發送請求,這個模塊會以json格式返回上傳的進度。配置比較簡單。
1)、首先打開這個模塊功能,在Nginx配置文件中http上下文里面,增加upload_progress proxied 5m;其中,proxied表示名稱(zone_name官方文檔),5m表示每次鏈接存放跟蹤信息的大小。另外,再設置返回格式為json,upload_progress_json_output;
2)、在上述的location = /upload中增加一個配置項track_uploads proxied 30s; 其中,proxied就是剛才在第一步設置的名字,30s表示每次鏈接處理完畢后,鏈接會保持30s。
3)、設置一個location來處理javascript發送請求。
location ^~ /progress {
report_uploads proxied; #GET此地址得到上傳進度
}
4)、還有一個參數考慮設置upload_progress_header ,這個值缺省是X-Progress-ID。有點類似SessionID,主要用在前臺需要在上傳文件的時候需要設置這個參數值,比如設置為uuid值。這樣javascript每次發送請求要獲取上傳進度時候,都需要帶上這個參數,這樣上傳進度跟蹤模塊才知道是返回那個鏈接的進度。
經過這三步驟,就把上傳進度跟蹤模塊配置好了。現在就需要對前臺腳本就行修改
5、修改第2步的前臺腳本
- <script type="text/javascript" src="http://192.168.1.203:7100/js/libs/ajaxfileupload.js" ></script>
- <script type="text/javascript">
- <strong>var interval = undefined;</strong>
- function uploadfile(){
- var uuid = "";
- for (var i = 0; i < 32; i++) {
- uuid += Math.floor(Math.random() *16).toString(16);
- }
- $.ajaxFileUpload({
- url:'http://192.168.1.203:7100/upload/<strong>?X-Progress-ID=' + uuid</strong>,//上傳的地址
- sercureuri:false,
- fileElementId:'fileToUpload',
- dataType:'json',
- success:function(data,status){
- if(typeof(data.error) != 'undefined'){
- if(data.error != '')
- alert(data.error);
- }
- else{
- alert(data.msg);
- }
- },
- error:function(data,status, e){
- alert(e);
- }
- });
- <strong> interval = window.setInterval(
- function () {
- getUploadProgress(uuid);
- },
- 2000
- );</strong>
- return false;
- }
- <strong> function getUploadProgress(uuid){
- etajax.sendRequest('http://192.168.1.203:7100/progress/',"GET","X-Progress-ID=" + uuid,getUploadProgressCallback);
- }
- function getUploadProgressCallback(type, json, http){
- if(type == "load"){
- var bar = document.getElementById('tp');
- if(json.state == "uploading"){
- var w = Math.floor(json.received * 100.0 / json.size) ;
- bar.innerHTML = w + "%";
- }
- /* we are done, stop the interval */
- if (json.state == 'done') {
- bar.innerHTML = "100%";
- window.clearTimeout(interval);
- }
- }
- } </strong>
- </script>
- <div>
- <input type="file" name="addfile" size="50" id="fileToUpload" />
- <input type="button" value="上傳" onclick="return uploadfile();"/>
- </div>
- <strong><div>
- <div id="tp">0%</div>
- </div></strong>
上述黑體就是增加的代碼,其中,有些函數是調用產品封裝好的函數,所以,不要全部照搬。主要是抓住以下幾個要點就可以了:
1、在上傳文件時候需要增加一個uuid,對應的參數就是upload_progress_header設置的,缺省是X-Progress-ID。
2、在請求獲取進度的時候,都要帶上這個uuid。
3、設定一個定時期,定時發送異步的GET方式請求,獲取進度數據。
4、返回的json格式是{"state":"uploading", "size":3232,"received":34},其中上傳完畢state值為done,如果發生錯誤會,state就是error,并且會返回status,錯誤編碼。
步驟就介紹在這里了。另外,javascript方式上傳文件,在用戶上傳文件時候,最好能獲取上傳文件大小,這樣可以提前告訴用戶是否超出允許上傳的大小值。但是,目前javascript方式獲取文件大小要兼容所有瀏覽器還是存在問題。我打算還是寫個flash,通過flash方式來獲取,比較保險。
來自:http://blog.csdn.net/waden/article/details/7040123
更多參考:http://blog.sina.com.cn/s/blog_704836f401014bpj.html
作者:justwinit@向東博客 專注WEB應用 構架之美 --- 構架之美,在于盡態極妍 | 應用之美,在于藥到病除
地址:http://justwinit.cn/post/6221/
版權所有。轉載時必須以鏈接形式注明作者和原始出處及本聲明!