准备工作
现在 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 错误等。