Chinaunix首页 | 论坛 | 博客
  • 博客访问: 325895
  • 博文数量: 104
  • 博客积分: 3025
  • 博客等级: 中校
  • 技术积分: 1150
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-02 11:12
文章分类

全部博文(104)

文章存档

2013年(1)

2011年(2)

2010年(30)

2009年(29)

2008年(8)

2007年(15)

2006年(17)

2005年(2)

我的朋友

分类:

2009-12-04 11:56:27


Nginx上传介绍

文档信息
  • 20091204 v1 暂不支持nginx upload progress
  • 20091207 v2 支持nginx upload progress,加入进度条支持,当前nginx版本0.7.63 Nginx-upload-progress-module版本0.6    nginx_upload_module版本2.0.10


目录

为什么要用nginx做PHP Post上传

Nginx上传介绍

如何搭建服务器

Nginx配置文件

范例

关于uploadprogress反馈的json信息

  

 
 
 
 
 
做PHP Post上传
现有的PHP上传:
apache+php
用户文件上传调用php上传引擎,文件上传到本地后,调用后续的逻辑进行处理。
 
 
问题:
  • apache+php本身效率的低下
  • 大文件上传的情况下,在一个文件没有被上传到本地之前,资源会一直被占用,这样无法承载更多的用户请求
 
 
Nginx上传的优点:
  • Nginx本身是一个高效能的服务
  • Nginx会将上传的文件先缓存在本地磁盘,然后通知后台服务器上传文件的信息

上传介绍

文件在POST上传到nginx服务器时,nginx会自己将这个文件先保存下来,然后再往后端发送。
在这个过程中,文件会被保存成一个临时文件,待文件传送完成后,nginx向后端(如apache+php)通知临时文件的文件信息(如上传文件原有的文件名、存在本地磁盘哪个目录下、临时文件名、文件的md5、文件的类型、文件的大小等)。
后端服务拿到这个文件名可以直接读取缓存的文件,进行迁移转码等后续逻辑。
 
框架图:

下载nginx
在下载
nginx、nginx_upload_module和nginx_uploadprogress_module
 
编译nginx参数
--add-module=path/to/nginx_uploadprogress_module
--add-module=path/to/nginx_upload_module
 
 
编译PHP需要的参数
--enable-fastcgi
--enable-force-cgi-redirect
 
 
编译安装spawn-fcgi(nginx通过FastCGI方式调用PHP)
 
 
启动spawn-fcgi

#/usr/local/sbin/spawn-fcgi -p 10080 -C 25 -u nobody -f /usr/local/php/bin/php-cgi

本例中,我们开启10080做为监听端口,打开25个php-cgi进程
 
Apache+PHP使用现有的服务即可

配置文件

Nginx.conf (红色部分为上传模块的设置黄色底纹为上传进度条模块设置)
worker_processes  20;
 

error_log  logs/error.log notice;

 
working_directory /usr/local/nginx;
 
events {

    worker_connections  1024;

}
 
http {

    include       mime.types;

    default_type  application/octet-stream;

    underscores_in_headers      on;

    add_header via $server_addr;

    # reserve 1MB under the name 'proxied' to track uploads

    upload_progress proxied 1m;

    server {

        listen       8000;
        #接受的上传文件的大小

        client_max_body_size 1024m;

 

        # Upload form should be submitted to this location

        location /upload {

            # Pass altered request body to this location

            upload_pass   @test;
 
            #上传限速,单位:兆/分钟,
            #默认值为0,代表没限制
            #upload_limit_rate 1m;
 
            #如果后台apache出现404等错误,会将上传缓存的文件删掉
            upload_cleanup 400 404 499 500-505;

            track_uploads proxied 30s;

            # Store files to this directory

            # The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist

            #上传文件缓存的目录,/tmp代表保存在tmp目录下,1代表/tmp/1-9目录
            upload_store /tmp 1;
 

            # 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$";

        }
 

        # Pass altered request body to a backend

        location @test {
            proxy_pass  

            #proxy_set_header request_body_file $request_body_file;

            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            #可以在这个里面自定义传给后台apache的变量,如X-Diocorns
            #proxy_set_header        X-Diocorns      $upload_tmp_path;

            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_set_header        X-Http-True-Client-Ip $server_name;
#proxy_redirect default;

        }

        location ~ .*\.(php|html)?$

        {

            include fcgi.conf;
            fastcgi_pass  127.0.0.1:10080;
            fastcgi_index index.php;

        }

 

        location ^~ /progress {

            # report uploads tracked in the 'proxied' zone

            report_uploads proxied;

        }

    }

}
 
 
 

本例中
Nginx 监听端口8000
Apache监听端口80

/usr/local/nginx/html/example.php
该页面在nginx下,nginx默认目录为/usr/local/nginx/html/

<form id="upload" enctype="multipart/form-data"
    action="/upload/" method="post"
    onsubmit="openProgressBar(); return true;" target="procFrame">
  <input type="hidden" name="MAX_FILE_SIZE" value="30000000" />
  <input name="userfile" type="file" label="fileupload" />
  <input type="submit" value="Send File" />
</form>
<iframe name="procFrame" width=1000 height=600 src=""></iframe>
  <div>
   <div id="progress" style="width: 414px; border: 1px solid black">
    <div id="progressbar"
       style="width: 1px; background-color: black; border: 1px solid white">
     &nbsp;
    </div>
   </div>
   <div id="tp">(status)</div>
  </div>

<script type="text/javascript">
 interval = null;
function createXmlHttpRequestObj()
{
 if (window.ActiveXObject) {
     xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
 }
 else if (window.XMLHttpRequest) {
     xmlHttp = new XMLHttpRequest();
 }
 return xmlHttp;
}

function fetch(uuid) {
 req = createXmlHttpRequestObj();
 req.open("GET", "/progress?X-Progress-ID="+uuid, 1);
 req.onreadystatechange = function () {
  if (req.readyState == 4) {
   if (req.status == 200) {

    var upload = eval(req.responseText);
    document.getElementById('tp').innerHTML = upload.state;

    /* change the width if the inner progress-bar */
    if (upload.state == 'uploading') {
     bar = document.getElementById('progressbar');
     w = 414 * upload.received / upload.size;
     //alert(upload.received);
     bar.style.width = w + 'px';
    }

    if (upload.state == 'done') {
     bar = document.getElementById('progressbar');
     w = 414;
     bar.style.width = w + 'px';
     /* we are done, stop the interval */
     window.clearTimeout(interval);
    }

   if (upload.state == 'error') {
        alert("upload file size is too large");
        window.clearTimeout(interval);
    }

   }
  }
 }
 req.send(null);
}
function openProgressBar() {

 uuid = "";
 for (i = 0; i < 32; i++) {
    uuid += Math.floor(Math.random() * 16).toString(16);
 }

 document.getElementById("upload").action="/upload/?X-Progress-ID=" + uuid;

 interval = window.setInterval(
   function () {
       fetch(uuid);
   },
   1000
 );
}
</script>



/var/www/upload/index.php
该页面在apache下,apache默认目录为/var/www/
Test upload
if ($_POST)

        {echo "there is post method";}

else

        {echo "sorry,no post method";}

phpinfo();
?>
 
页面操作:
 
在浏览器里输入
选择本地文件上传(1024.dat),点击uploadss按钮
在跳转的页面中可以看到打印出来的there is post method,在phpinfo里看到
_REQUEST["file1_name"]
1024.dat
_REQUEST["file1_content_type"]
no value
_REQUEST["file1_path"]
/tmp/2/0010517642
_REQUEST["file1_md5"]
6da78ab56bd01c55fc1e7e066c71d54c
_REQUEST["file1_size"]
1051650
_REQUEST["submit"]
Uploadss


解释:
_REQUEST["file1_name"]表示上传文件名为1024.dat
_REQUEST["file1_content_type"]表示该文件的文件类型,本例中未判别出文件格式,打印no value
_REQUEST["file1_path"]表示缓存文件的位置
_REQUEST["file1_md5"]表示文件的MD5
_REQUEST["submit"]表示上传按钮的value为Uploadss

关于上传进度条:
在example.php页面的下面,也可以看到黑色的进度条随着上传文件的大小在走动

关于uploadprogress反馈的json信息



* the upload request hasn't been registered yet or is unknown: 

   new Object({ 'state' : 'starting' }) 

* the upload request has ended: 

   new Object({ 'state' : 'done' }) 


* the upload request generated an HTTP error 

   new Object({ 'state' : 'error', 'status' : }) 

 one error code that can be of use to track for the client is 413 (request entity too large). 


* the upload request is in progress: 

   new Object({ 'state' : 'uploading', 'received' : , 'size' : })


阅读(2799) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-03-09 17:29:22

按文中的方法测试 不成功不知道为什么 日志文件如下 192.168.3.1 - - [09/Mar/2010:14:23:22 +0000] "?1\x1A\x07繛pV?B\x18x頢A嶾x15?Wb攟诘塞\x17\x16羌X匟?個搈\x1F笝瘺严沓\x01\x1A齽篚羂x5CB\x22譬>查p龈豛x04c?諙?蕸~?Z肞?軫醄>魄?\x01?J鶨\x04粝?黽\x17Gt4??$鯪?搥O`丈膊娋畃??菌妁桀繹?逗噁\x1B\x14M&刬?琧f1腝?矆?椆?g瀗|?鹐骪x1B+奬x18単'\x10aC=x芌\x1C掆\x1E\x22?羂x04TB8?\x1Fk\x12T彑3k鞸2\x06屟\x06\x19p\x0E@秪泄N?栾騖x13?嬩?(陃\x1D懄hJd硎T\x16?2W&卖}%雗蚛x0E蓅`惐齌頴琝x04