<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    nginx upload module的使用

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    現在的網站,總會有一點與用戶交互的功能,例如允許用戶上傳頭像,上傳照片,上傳附件這類的。PHP寫的程序,對于上傳文件效率不是很高。
    幸好,nginx有一個名為upload的module可以解決這個問題。網絡上已經有很多關于upload module的文章,但是大部分都是介紹編譯安裝這些的,對于一些細節敘述不是很清楚,于是自己寫了這篇。
    參考了很多其他人的文檔,在此致謝,詳細見參考文檔部分。

    一、upload module的工作原理
    nginx upload module模塊通過nginx服務器來接受用戶上傳的文件,它自動分析客戶端的上傳請求,將上傳的文件保存到 upload_store 所指向的目錄位置。
    然后這些文件信息將被從原始的請求中剔除,重新組裝好上傳參數后轉交到后端由 upload_pass 指定的location去處理,這樣后端就可以任意處理上傳的文件。
    每一個上傳的 file 字段值將可以由upload_set_form_field 指定的值替換。
    上傳的文件可以通過$upload_tmp_path 變量訪問到。
    上傳的文件經過處理以后,由 upload_cleanup 指定的條件控制刪除清理。

    以上表達可能不夠直觀,我們舉個例子,假如我們使用如下一個頁面作為上傳頁面:

    [root@Nginx-Mod-DEV wwwroot]# cat index.html
    <html>
    <head>
    <title>Test upload</title>
    </head>
    <body>
    <h2>Select files to upload</h2>
    <form name="upload" method="POST" enctype="multipart/form-data" action="/upload">
    <input type="file" name="file1"><br>
    <input type="file" name="file2"><br>
    <input type="submit" name="submit" value="Upload">
    <input type="hidden" name="test" value="value">
    </form>
    </body>
    </html>

    那么我們選擇兩個文件,點擊"Upload"按鈕以后,nginx upload module會接收上傳來的文件,將上傳的文件保存到 upload_store 所指向的目錄位置。
    然后上傳的文件信息將被從原始的請求中剔除,根據nginx.conf中的配置重新組裝好上傳參數,然后轉到后端由 upload_pass 指定的位置去處理。
    假如我們上傳得兩個文件分別名為:Picture 1.png和Picture 2.png,那么upload module接收文件以后,會傳遞給后端類似下邊這樣的一組參數:

    "file1.path"=>"/tmp/0000123458",
    "file2.path"=>"/tmp/0000123459",
    "file1.content_type"=>"image/png",
    "file2.content_type"=>"image/png",
    "file1.name"=>"Picture 1.png",
    "file2.name"=>"Picture 2.png",

    這樣后端的PHP代碼就可以使用$_POST變量獲取這些參數來處理上傳進來的文件了。下邊是一個簡單的示例,只是顯示出相應的變量的值,然后根據文件的MD5值,取第一個字符作為對應的一級目錄名稱,取最后一個字符作為第二級目錄名稱,然后將上傳的文件移動到相應的目錄中。

    <?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 "^.*$";

    upload_set_form_field可以使用的幾個變量
        $upload_field_name    表單的name值
        $upload_content_type    上傳文件的類型
        $upload_file_name    客戶端上傳的原始文件名稱
        $upload_tmp_path    文件上傳后保存在服務端的位置

    upload_aggregate_form_field 可以多使用的幾個變量,文件接收完畢后生成的
        $upload_file_md5    文件的MD5校驗值
        $upload_file_md5_uc    大寫字母表示的MD5校驗值
        $upload_file_sha1    文件的SHA1校驗值
        $upload_file_sha1_uc    大寫字母表示的SHA1校驗值
        $upload_file_crc32    16進制表示的文件CRC32值
        $upload_file_size    文件大小

    三、編譯安裝的步驟

    這個很簡單,也有很多人寫了不錯的文章,在此流水賬記錄一下。
        
    1.編譯環境準備---這部分不需要,因為我要用到nginx-lua-module,所以列在這里了

    [ lua 5.1 ]
    wget http://www.lua.org/ftp/lua-5.1.5.tar.gz
    tar xvzf lua-5.1.5.tar.gz
    cd lua-5.1.5/src
    make linux
    cd ..
    make install

    此處默認安裝位置是/usr/local,如果安裝到其他位置需要:
    export LUA_LIB=/path/to/lua/lib
    export LUA_INC=/path/to/lua/include

    另外,lua-ngix-module目前版本與lua 5.2不兼容,不要選擇lua 5.2

    [ pcre 8.30 ]
    wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz
    tar xvzf pcre-8.30.tar.gz

    2.編譯nginx

    [ chaoslawful-lua-nginx-module ]---這部分不需要
    https://github.com/chaoslawful/lua-nginx-module/downloads

    [ nginx_upload_module-2.2.0 ]
    wget http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
    tar xvzf nginx_upload_module-2.2.0.tar.gz

    [ nginx 1.0.15 ]
    wget http://nginx.org/download/nginx-1.0.15.tar.gz
    tar xvzf nginx-1.0.15.tar.gz
    cd nginx-1.0.15
    ./configure --prefix=/usr/local/nginx --with-pcre=../pcre-8.30 --add-module=../nginx_upload_module-2.2.0 --add-module=../chaoslawful-lua-nginx-module-8d28785 --without-mail_pop3_module --without-mail_imap_module  --without-mail_smtp_module --with-http_ssl_module  --with-http_stub_status_module  --with-http_gzip_static_module
    make && make install

    四、一些常見的問題

    疑問1.upload_set_form_field的變量名
    http://serverfault.com/questions/152194/merging-variable-with-string-in-config-file

    Question:
    I the have following setup in my conf file
    upload_set_form_field $upload_field_name.name "$upload_file_name";
    But I want change chosen param name to:
    upload_set_form_field ($upload_field_name+"[name]") "$upload_file_name";
    So I can get "attachment[name]" but this doesn't work. I would be very happy if someone could help me with merging variables with string in nginx config file :).

    Anwser:
    Nginx does not have a concatenation character, rather it's based on valid and invalid characters, for instance in the directive:
    try_files $uri $uri/ @fallback;
    $uri is the variable and / is a string to append since / cannot be in a variable name.
    Similarly you should try
    $upload_field_name[name] "$upload_file_name";
    If this doesn't work then try.
    set $foo [name];
    $upload_field_name$foo "$upload_file_name";
    I cannot say if the upload module will even allow this, though. Minor syntax errors might also be present.

    疑問2.upload模塊不支持輸入數組
    http://newbdez33.blogspot.com/2009/05/nginx-upload-module-does-not-support.html

    Nginx upload module does not support input array for PHP
    Please refer below email,
        Jacky Zhang wrote:
        > Hi Valery,
        >
        > It's fine if I using nginx upload module to upload a signle file.
        > but It look incorrect that when I use a input like this:
        >
        >

        <input type="file" name="userfiles[]" />

        >
        > Do you have any suggestion?

        No, arrays won't work, you have to list every file input field individually.
        --
        Best regards,
        Valery Kholodkov
        
    疑問3.如何限制上傳文件的大小

    http://wiki.nginx.org/HttpCoreModule#client_max_body_size

    php.ini中要設置一下

    file_uploads     on     是否允許通過HTTP上傳文件的開關。默認為ON即是開
    upload_tmp_dir     –     文件上傳至服務器上存儲臨時文件的地方,如果沒指定就會用系統默認的臨時文件夾
    upload_max_filesize     8m     望文生意,即允許上傳文件大小的最大值。默認為2M
    post_max_size     8m     指通過表單POST給PHP的所能接收的最大值,包括表單里的所有值。默認為8M

    一般地,設置好上述四個參數后,在網絡正常的情況下,上傳<=8M的文件是不成問題
    但如果要上傳>8M的大體積文件,只設置上述四項還一定能行的通。除非你的網絡真有100M/S的上傳高速,否則你還得繼續設置下面的參數。
    max_execution_time     600     每個PHP頁面運行的最大時間值(秒),默認30秒
    max_input_time     600     每個PHP頁面接收數據所需的最大時間,默認60秒
    memory_limit     8m     每個PHP頁面所吃掉的最大內存,默認8M

    另外還要在nginx.conf中做設置。
    upload_max_file_size <size>   這個是個軟限制
    client_max_body_size 這個是硬限制(默認1m)

    附錄: nginx.conf的配置

    # Generic startup file.
    user nginx;
    worker_processes  4;
    worker_rlimit_nofile 65536;

    error_log  /var/log/nginx/error.log;
    pid        /var/run/nginx.pid;

    # Keeps the logs free of messages about not being able to bind().
    #daemon     off;

    events {
            use epoll;
            worker_connections  10240;
    }

    http {
    #       rewrite_log on;

            include mime.types;
            default_type       application/octet-stream;
            access_log         /var/log/nginx/access.log;
            sendfile           on;
    #       tcp_nopush         on;
            keepalive_timeout  3;
    #       tcp_nodelay        on;

            gzip on;
            gzip_http_version 1.1;
            gzip_comp_level 2;
            gzip_types    text/plain text/css
                          application/x-javascript text/xml
                          application/xml application/xml+rss
                          text/javascript;
            client_max_body_size 13m;
            index index.php index.html index.htm;

            server {
            listen 80;
            server_name image.demo.com;
            access_log /var/log/nginx/image.access.log;
            location / {
            index index.html;
            root  /images;
            }
            }

            server{
            listen 80;
            server_name upload.demo.com;
            root  /var/wwwroot;

            # 上傳頁面會把文件上傳到這個location
            location /upload {
            # 文件上傳以后轉給后端的PHP代碼去處理
            upload_pass /movefile.php;

            # 上傳的文件臨時存儲位置
            # 此處注意,我把臨時文件目錄放到了tmpfs中,為了速度,但有丟失數據的風險!
            upload_store /dev/shm;
            
            # Allow uploaded files to be read only by user
            upload_store_access user:r;

            # Set specified fields in request body
            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";


            # Inform backend about hash and size of a file
            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 "^submit$|^description$";

            upload_cleanup 400 404 499 500-505;
            }

    #        location @test {
    #        proxy_pass   http://127.0.0.1;
    #        }

            location ~ \.php {
                fastcgi_pass  127.0.0.1:9000;
                fastcgi_index index.php;
                include fastcgi.conf;
            }
            }

    }

    參考文檔:

    http://blog.martinfjordvald.com/2010/08/file-uploading-with-php-and-nginx/

    http://brainspl.at/articles/2008/07/20/nginx-upload-module

    http://www.phpabc.cn/nginxphp-fpmyou-hua-post-xing-neng.html

    http://deidara.blog.51cto.com/400447/389873

    http://anerg.com/read.php?55

    http://t.lava.cn/blog.php?id=23726

    http://blog.joshsoftware.com/2010/10/20/uploading-multiple-files-with-nginx-upload-module-and-upload-progress-bar/

    http://matthewhutchinson.net/2010/1/6/nginx-upload-module-with-paperclip-on-rails

    http://b.oldhu.com/2009/06/09/uploading-multiple-large-files-to-a-rails-application/

    http://www.tutorialchip.com/php-upload-class/

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全