码迷,mamicode.com
首页 > Web开发 > 详细

面试题笔记:实现Nginx Upload 模块 功能上传文件。

时间:2016-07-08 23:01:43      阅读:1123      评论:0      收藏:0      [点我收藏+]

标签:

linux服务器开发测评题目
————————————————————————————

搭建一个nginx服务器,能完成文件上传功能。主要构成有:
<1> 用于测试服务器上传功能用的前端html页面
<2> nginx web服务器,包括了文件上传功能模块,注意配置好配置文件
<3> 对于上传成功的文件,给前端返回upload successfully信息

动手搭建完成后,针对上面的几点要求截几张图,同时把前端html页面,nginx配置文件,和假如需要使用的业务逻辑代码(如php/java等),通过邮件发送给我。

附注说明:整个题目代码量比较少,旨在测试分析问题,快速学习,解决问题的能力。

 

分析(也许我表达的让人难以理解,但是我想说一句,直接实践是最好的。。。。。):

一、Ningx 上传(

1.安装Nginx 的模块文件(upload):https://www.nginx.com/resources/wiki/modules/upload/,默认Nginx 肯定是没安装这个扩展模块的,你可以准备删除Nginx重新去官网下载一个最新稳定版本,并且进行编译吧。。。。。。

 

# Upload form should be submitted to this location
    location /upload {

# Pass altered request body to this location
        upload_pass   /upload.php;

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

这里是扔到10个文件夹里去 upload_store /usr/share/nginx/html/file 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$"; }
这里是个大坑,因为如果默认就是当前的服务器的80端口,配置这个是会出错的,我就直接没用代理,直接
        upload_pass   /upload.php;
#如果是当前端口,设置proxy_pass会出现错误 
# Pass altered request body to a backend
#location @test {
# proxy_pass htpp://127.0.0.1;
#}

2.Nginx的某个路由(看我下面的配置文件)检测到上传请求后,会分别将各个你定义的form file name,上传到不同的文件夹,一共是10个(创建10个文件夹,命名0 1  2 3 ...),文件位置自定义(但一定要包含那10个文件夹,这个切记),一定要检测你创建的文件夹Nginx是否具有写入权限,这个可以自己看log(这个相当重要),如果你配置完成后想玩点新花样,可以自己玩玩,还可以限制上传速度之类的,而且可以做转发,如果你配置的代理服务器本身就做了URL反向代理,那肯定可以转发上传文件到多个Nginx服务器(上传文件提交信息,比如文件位置在哪儿之类的。)去滴。。。

 

二、直接PHP上传

PHP上传文件,本身就要配置Nginx 模块,所以很多人会搞混,其实两者是有差异的,

正常的上传流程:html 提交上传文件,nginx 收到后 扔到tmp目录,PHP收到后,把TMP的上传文件扔到自己想放的文件夹。

 

 

-------------------------------------------------------------------

 

两者都需要编写HTML,直接提交给Nginx ,在Upload Modules 配置好了,是可以直接接受多个文件上传的,不过既然面试题就是叫我实现一个文件上传,那我还写那么多干啥!反正没卵用。。。。

<!-- 这是提交给nginx -->
<html lang="CN">
<head>
    <meta charset="UTF-8">
    <title>Test upload</title>
</head>
<body>
<h2>Select files to upload</h2>
<form enctype="multipart/form-data" action="/upload" method="post">
    <input type="file" name="file"><br>
<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>
<!-- 这是直接提交给php -->
<html lang="CN">
<head>
    <meta charset="UTF-8">
    <title>Test upload</title>
</head>
<body>
<h2>Select files to upload</h2>
<form enctype="multipart/form-data" action="/upload.php" method="post">
    <input type="file" name="file"><br>
    <input type="submit" name="submit" value="Upload">
    <input type="hidden" name="test" value="value">
</form>
</body>
</html>

  

 

1:通过配置Ningx 安装 Upload Modules 进行 文件上传 再从PHP 接受 Ningx POST过来的参数。

2.直接通过编写PHP,从HTML 负责文件上传

 

server {
    listen       80;
    server_name  localhost;
charset utf-8;

access_log  /usr/local/nginx/logs/access.log  main;

    client_max_body_size 100m;

# Upload form should be submitted to this location
    location /upload {

# Pass altered request body to this location
        upload_pass   /upload.php;

# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
        upload_store /usr/share/nginx/html/file 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$";
    }
#如果是当前端口,设置proxy_pass会出现错误
# Pass altered request body to a backend
    #location @test {
    #   proxy_pass   htpp://127.0.0.1;
    #}
    location / {
        root           /usr/share/nginx/html/work/public;
        index  index.html index.htm index.php;
    }

    error_page  404              /404.html;

# redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }


    location ~ \.php$ {
        root           /usr/share/nginx/html/work/public;
        fastcgi_pass   unix:/opt/remi/php70/root/run/lock/php-fcgi.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires       15d;
    }
    location ~ .*\.(js|css)?$
    {
        expires       1d;
    }
}

  

自己感受~~~~~

 

然后贴上PHP 代码:只是对应面试题,你可别真瘠薄用我这套代码,出事儿了 我不管,别找我。。。。。

 

<?php
header(‘Content-Type: text/html;charset=UTF-8‘);
//文件后缀=>文件类型
$type = [‘.pdf‘ => ‘application/pdf‘];

const FILE_DIR = ‘/usr/share/nginx/html/work/‘;


//如果非nginx upload module 上传文件
if (count(($file = $_FILES[‘file‘])) > 0) {

    if ($file[‘error‘] == 0) {

        //判断文件类型是否存在,文件后缀是我们自己的key去定义
        if ($fileType = array_search($file[‘type‘], $type)) {

            //以当前的时间命名目录
            $date_dir = date(‘Y-m-d‘, time());

            //如果目录没创建,我们就自己创建一个
            if (!is_dir(FILE_DIR . $date_dir)) {

                if (!mkdir(FILE_DIR . $date_dir)) {
                    return header(‘location:503.html‘);
                }
            }

            //文件的MD5+当前unix时间戳+一个5位随机数,如果此处需求频繁也可以用微秒时间戳

            $filename = FILE_DIR . $date_dir . ‘/‘ . (md5_file($file[‘tmp_name‘]) . time() . rand(9999, 99999)) . $fileType;


            //生成新的文件
            if (rename($file[‘tmp_name‘], $filename)) {

                return header(‘Location: success.html‘);

            }

        }
    }

    switch ($file[‘error‘]) {
        case 1:
            http_response_code(400);
            exit(‘文件大小超出了服务器的空间大小‘);
        case 2:
            http_response_code(400);
            exit(‘要上传的文件大小超出浏览器限制‘);
        case 3:
            http_response_code(400);
            exit(‘文件仅部分被上传‘);
        case 4:
            http_response_code(404);
            exit(‘没有找到要上传的文件‘);
        case 5:
            http_response_code(503);
            exit(‘服务器临时文件夹丢失‘);
        case 6:
            http_response_code(503);
            exit(‘文件写入到临时文件夹出错‘);
    }
}


//如果是nginx upload module
if (count(($file = $_POST)) > 0) {

    //判断文件类型是否存在,文件后缀是我们自己的key去定义
    if ($fileType = array_search($file[‘file_content_type‘], $type)) {

        //以当前的时间命名目录
        $date_dir = date(‘Y-m-d‘, time());

        //如果目录没创建,我们就自己创建一个
        if (!is_dir(FILE_DIR . $date_dir)) {

            if (!mkdir(FILE_DIR . $date_dir)) {
                return header(‘location:503.html‘);
            }
        }

        //文件的MD5+当前unix时间戳+一个5位随机数,如果此处需求频繁也可以用微秒时间戳

        $filename = FILE_DIR . $date_dir . ‘/‘ . (md5_file($file[‘file_path‘]) . time() . rand(9999, 99999)) . $fileType;


        //生成新的文件
        if (rename($file[‘file_path‘], $filename)) {

            return header(‘Location: success.html‘);

        }
    }
}


http_response_code(400);
exit(‘错误操作方式!‘);

 

面试题笔记:实现Nginx Upload 模块 功能上传文件。

标签:

原文地址:http://www.cnblogs.com/rootarvin/p/5654679.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!