乐趣区

Nginx-Tips-Php-Uploading-Progress-Bar-0010

准备工作

现在 nginx-upload-module 模块已经加入到 Nginx,但还不能直接使用,还有一些准备工作要做。

准备 JavaScript 脚本

首先,下载或直接链接 jQuery.js,因为模块要配合使用 jQuery 来控制 HTML 元素显示进度。

<head>
...
<script type="text/javascript" src="/js/jquery.js"></script>

...
</head>

<head>
...

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

...
</head>

关键是还需要另一个脚本:jquery.uploadProgress.js。可以从这里下载。


注意


别忘了在你的页面中包含该脚本。
同样滴,由于 jQuery 已经变化,不再支持 $.browser.safari,所以我们需要修改 jquery.uploadProgress.js。
将所有这样的代码:

$.browser.safari

修改成:

navigator.userAgent.match(/safari/i)

该修正参考自这里,原意是针对 IE 的,可以依样画葫芦。
原文这么说:

...

as far of jquery 1.9 jQuery.browser was removed, adn admin_menu get this error:
"Uncaught TypeError: Cannot read property'msie'of undefined" (admin_menu.js - line:223)

For quick fix use this code:
change line 223:
- if ($.browser.msie && parseInt(jQuery.browser.version) == 6) {+ if (navigator.userAgent.match(/msie [6]/i)) {...

修改 Nginx 配置文件

首先要修改 /etc/nginx.conf 文件,加大允许上传的文件尺寸,并配置上传进度报告的尺寸间隔,这里设置为 50k 一报告。

http {
    ##
    # Basic Settings
    ##
    
    ...

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;
    
    # REV:igame@Dec-22-2013: Change size from 2m to 256m.
    client_max_body_size 256M;
    
    # REV:igame@Dec-22-2013: Followed the instruction of http://wiki.nginx.org/HttpUploadProgressModule
    upload_progress proxied 50k;

        ...

再修改 /etc/nginx/sites-available/default 文件中的 location ~ .php$ 小节,根据指南,track_uploads 必须是最后一行。

location ~ \.php$ {
        ...
    # track uploads in the 'proxied' zone
        # remember connections for 30s after they finished
        track_uploads proxied 30s;
}

并添加下面的内容:

location ^~ /progress {
    upload_progress_json_output;
    report_uploads proxied;
}

使用 upload_progress_json_output 是因为 jQuery 会按 json 模式解析数据,不加这一行将导致解析失败,也就不能显示进度了。

修改 PHP 配置

打开 /etc/php5/fpm/php.ini 文件,修改以下内容:

...
; Whether to allow HTTP file uploads.
; http://php.net/file-uploads
file_uploads = On

...
;post_max_size = 8M
post_max_size = 256M

...

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
;upload_max_filesize = 2M
upload_max_filesize = 256M

...

允许文件上传,并允许上传最大 256M 的文件。如果文件太小了,一忽儿就完毕了,也就无法看到进度了。

编写页面

现在编写上传页面,假设叫 learn.php,内容如下:

<html>
<head>
    <script type="text/javascript" src="/js/jquery.js"></script>
    <script type="text/javascript" src="/js/jquery.uploadProgress.js"></script>
    <!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> -->
    
    <style>
        .bar {width: 300px;}
          
        #progress {
          background: #eee;
          border: 1px solid #222;
          margin-top: 20px;
        }

        #progressbar {
          width: 0px;
          height: 24px;
          background: #333;
        }
    
    </style>
</head>
<body>

<form id="form1" action="ulfile.php" method="POST" enctype="multipart/form-data">
Filename: <input type="file" name="file1" />
<input type="submit" value="Upload" />
</form>

<div id="uploading">
  <div id="progress" class="bar">
    <div id="progressbar"> </div>
    <div id="percents"></div>
  </div>
</div>

<script type="text/javascript">
$(function() {$('form').uploadProgress({
        /* scripts locations for safari */
        jqueryPath: "/js/jquery.js",
        uploadProgressPath: "/js/jquery.uploadProgress.js",
        start: function() {// Add start code here.},
        /* 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: 500
      });
    });
</script>
</body>
</html>

注意


该页面可能不能在你的机器上运行,因为脚本路径与你的实际情况不一致。

再编写上传完成后的页面,假设名字叫 ulfile.php,内容如下:

<?php
  if ($_FILES["file1"])
    {
    echo "Congratulations!<br />";

        if ($_FILES["file1"]["error"] > 0)
        {echo "Error:" . $_FILES["file1"]["error"] . "<br />";
        }
        else
        {echo "Source File:" . $_FILES["file1"]["name"] . "<br>";
            echo "Type:" . $_FILES["file1"]["type"] . "<br>";
            echo "Size:" . round($_FILES["file1"]["size"] / 1024) . "kB<br>";
            echo "Stored in:" . $_FILES["file1"]["tmp_name"];
            echo "<br />";
        
            $uploaddir = './upload/'; // /usr/share/nginx/www/upload/';
                        // 注意,英文文件名不需要解码,但中文需要。// $uploadfile = $uploaddir . basename($_FILES['file1']['tmp_name']);
            $uploadfile = $uploaddir . html_entity_decode(basename($_FILES['file1']['name']));
            
            echo "Destination:" . $uploadfile . "<br />";
        
            if (move_uploaded_file($_FILES['file1']['tmp_name'], $uploadfile))
            {
                echo "File successfully uploaded.<br />";
                /* 如果不想保存,只是测试进度条,可以在上传完成后立即删除。if (!unlink($uploadfile))
                    echo "Can't delete the uploaded file.<br />";
                */
            }
            else
                echo "Failed to save file.<br />";
        }
    }

注意,如果遇到目录问题,比如这里使用 upload 目录,而你没有,你需要建立这样的目录并设置相当权限(root)。
好了,现在可以心情的享受你的上传进度条了,小心不要爆了你的硬盘。


Tips


问题主要集中在路径上,比如 js 的路径,目录的权限,致命的 413 错误等。

退出移动版