菜鸟学习Nginx之入门开发留言板

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxb249/article/details/84786822

本篇算是学习Nginx开山之作,后面还有会具体解析源码。

利用Nginx实现了一个登录、留言板、文件上传功能,功能非常简单。但是对于如何开发一个Nginx模块来说已经足够,希望能够起到抛砖引玉的效果。

一、效果

登录界面: http://192.168.1.10/login.html  用户名和密码随意

首页: http://192.168.1.10/index.html 

文件上传:http://192.168.1.10/resources.html

二、搭建

我学习Nginx的版本号是1.12.2,大家可以根据各自具体情况进行学习或者搭建服务。

2.1 增加module

在Nginx源码根目录中创建子目录webservice,将下面config文件以及.c放到其中。

ngx_addon_name=ngx_http_webservice_module
HTTP_MODULES="$HTTP_MODULES ngx_http_webservice_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_webservice_module.c"
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

static char*
ngx_http_webservice_login(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t
ngx_http_webservice_login_handler(ngx_http_request_t *r);
static ngx_int_t
ngx_http_webservice_msgs_post_handler(ngx_http_request_t *r);
static char*
ngx_http_webservice_msgs_post(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t
ngx_http_webservice_messages_handler(ngx_http_request_t *r);
static char*
ngx_http_webservice_messages(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void 
ngx_http_webservice_msgs_handler(ngx_http_request_t *r);
static void
ngx_http_get_param_value(ngx_log_t *log, char *body, char *key, ngx_str_t *value);
static void 
ngx_http_webservice_upload_body_handler(ngx_http_request_t *r);

static ngx_int_t
ngx_http_webservice_upload_handler(ngx_http_request_t *r);

static char*
ngx_http_webservice_upload(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void 
ngx_http_webservice_upload_writefile(ngx_pool_t *pool, FILE *file, const char* filename, size_t length);
static char*
ngx_http_webservice_uploadlist(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t
ngx_http_webservice_uploadlist_handler(ngx_http_request_t *r);

typedef struct {
  ngx_str_t email;
  ngx_str_t subject;
  ngx_str_t content;
}ngx_http_webservice_messages_t;

typedef struct ngx_http_webservice_messages_chain_s ngx_http_webservice_messages_chain_t;

struct ngx_http_webservice_messages_chain_s{
  ngx_http_webservice_messages_t msg;
  ngx_http_webservice_messages_chain_t *next; 
};
static ngx_uint_t ngx_http_webservice_messages_count = 0;
static ngx_http_webservice_messages_chain_t *messages_header = NULL;

static ngx_http_module_t ngx_http_webservice_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};

static ngx_command_t ngx_http_webservice_commands[] = {
    {
        ngx_string("login"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_webservice_login,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    {
        ngx_string("messages"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_webservice_messages,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    {
        ngx_string("msgs_post"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_webservice_msgs_post,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    {
        ngx_string("upload"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_webservice_upload,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    {
        ngx_string("uploadlist"),
        NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
        ngx_http_webservice_uploadlist,
        NGX_HTTP_LOC_CONF_OFFSET,
        0,
        NULL
    },
    ngx_null_command
};

ngx_module_t ngx_http_webservice_module = {
    NGX_MODULE_V1,
    &ngx_http_webservice_ctx,
    ngx_http_webservice_commands,
    NGX_HTTP_MODULE,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NGX_MODULE_V1_PADDING
};

static char*
ngx_http_webservice_login(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_webservice_login_handler;
    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_webservice_login_handler(ngx_http_request_t *r)
{
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if  (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
    {
        return rc;
    }
    //校验用户名和密码

    //校验通过跳转到首页
    //ngx_buf_t *b;
    //b = ngx_palloc(r->pool, sizeof(ngx_buf_t));

    #if 0
    u_char *filename = (u_char*)"/usr/local/nginx/html/index.html";
    b->in_file = 1;
    b->file = ngx_palloc(r->pool, sizeof(ngx_file_t));
    b->file->fd = ngx_open_file(filename , NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0);
    b->file->log = r->connection->log;
    b->file->name.data = filename;
    b->file->name.len = strlen((const char*)filename);
    if (b->file->fd <= 0) {
        return NGX_HTTP_NOT_FOUND;
    }

    if (ngx_file_info(filename, &b->file->info) == NGX_FILE_ERROR) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    r->headers_out.content_length_n = b->file->info.st_size;
    ngx_str_t type = ngx_string("text/html");
    r->headers_out.content_type = type;
    b->file_pos = 0;
    b->file_last = b->file->info.st_size;

    //清理文件句柄
    ngx_pool_cleanup_t *cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_t));
    if (cln == NULL) {
        return NGX_ERROR;
    }
    cln->handler = ngx_pool_cleanup_file;
    ngx_pool_cleanup_file_t *clnf = cln->data;
    clnf->fd = b->file->fd;
    clnf->name = b->file->name.data;
    clnf->log = r->pool->log;
    #endif

    r->headers_out.status = NGX_HTTP_MOVED_TEMPORARILY;
    ngx_table_elt_t *location = ngx_list_push(&r->headers_out.headers);
    if (location == NULL) {
        return NGX_ERROR;
    }   
    location->hash = 1;
    ngx_str_set(&location->key, "Location");
    ngx_str_set(&location->value, "/index.html");
    r->headers_out.location = location;
    r->header_only = 1;

    //发送http head
    return ngx_http_send_header(r);

    //发送http body
    //ngx_chain_t out;
    //out.buf = b;
    //out.next = NULL;
    //return ngx_http_output_filter(r, &out);
}

static char*
ngx_http_webservice_messages(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_webservice_messages_handler;
    return NGX_CONF_OK;
}

ngx_str_t *ngx_http_webservice_getmessages()
{
    return NULL;
}

static u_char* ngx_http_webservice_messages_data(ngx_http_request_t *r)
{
    ngx_uint_t pos = 0;
    u_char *json = NULL;
    if (messages_header == NULL) {
        return (u_char*)"[]";
    }
    
    json = (u_char*)ngx_palloc(r->pool, ngx_http_webservice_messages_count * 1024);//每条记录1024字节
    ngx_memset(json, 0, ngx_http_webservice_messages_count * 1024);
    if (json == NULL) {
        return json;
    }
    ngx_http_webservice_messages_chain_t *item = messages_header;
    json[0] = '[';
    pos++;
    while (item) {
        ngx_sprintf(json+pos, "{\"Email\":\"%s\",\"Subject\":\"%s\",\"Content\":\"%s\"}",
                    item->msg.email.data,
                    item->msg.subject.data,
                    item->msg.content.data);
        pos = ngx_strlen(json);                    
        item = item->next;
        if (item != NULL) {            
            json[pos++] = ',';
        }
    }    
    json[pos] = ']';
    return json;
}

static ngx_int_t
ngx_http_webservice_messages_handler(ngx_http_request_t *r)
{    
    
    if (r->method != NGX_HTTP_GET)
    {
        return NGX_HTTP_NOT_ALLOWED;
    }
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK)
    {
        return rc;
    }
    
    u_char* body = ngx_http_webservice_messages_data(r);
    ngx_int_t len = ngx_strlen(body);
    ngx_str_t type = ngx_string("application/json");
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_type = type;
    r->headers_out.content_length_n = len;
    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
    {
        return rc;
    }

    ngx_buf_t *b = ngx_create_temp_buf(r->pool, len);
    if (b == NULL)
    {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ngx_memcpy(b->pos, body, len);
    b->last = b->pos + len;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;
    return ngx_http_output_filter(r, &out);
}

static char*
ngx_http_webservice_msgs_post(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_webservice_msgs_post_handler;
    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_webservice_msgs_post_handler(ngx_http_request_t *r)
{
    if (r->method != NGX_HTTP_POST)
    {
        return NGX_HTTP_NOT_ALLOWED;
    }
    //异步接收body
    ngx_uint_t rc = ngx_http_read_client_request_body(r, ngx_http_webservice_msgs_handler);
    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }
    return NGX_DONE;
}

static void 
ngx_http_webservice_msgs_handler(ngx_http_request_t *r) 
{
  u_char* data_buf = NULL;
  size_t content_length = 0;
  size_t body_length = 0;
  size_t buf_length = 0;
  ngx_chain_t *bufs = r->request_body->bufs;
  ngx_buf_t *buf = NULL;

  //获取body
  content_length = r->headers_in.content_length_n;
  data_buf = (u_char*)ngx_palloc(r->pool, content_length + 1);
  while (bufs)
  {
      buf = bufs->buf;
      bufs = bufs->next;
      buf_length = buf->last - buf->pos ;
      if(body_length + buf_length > content_length)
      {
          ngx_memcpy(data_buf + body_length, buf->pos, content_length - body_length);
          body_length = content_length ;
          break;
      }
      ngx_memcpy(data_buf + body_length, buf->pos, buf->last - buf->pos);
      body_length += buf->last - buf->pos;
  }
  if ( body_length )
  {
      data_buf[body_length] = 0;
  }

  ngx_http_webservice_messages_chain_t *node = NULL;
  node = ngx_alloc(sizeof(ngx_http_webservice_messages_chain_t), 
                            r->pool->log);
  node->next = messages_header;
  messages_header = node;
  ngx_http_webservice_messages_count++;
  
  ngx_http_get_param_value(r->pool->log, (char *)data_buf, "email", &node->msg.email);
  ngx_http_get_param_value(r->pool->log, (char *)data_buf, "subject", &node->msg.subject);
  ngx_http_get_param_value(r->pool->log, (char *)data_buf, "message", &node->msg.content);

  //由于不需要返回响应 只需要响应header即可 因此不需要设置output
  r->headers_out.status = NGX_HTTP_OK; 
  r->headers_out.content_length_n = 0;
  r->header_only = 1;
  //r->headers_out.content_type = type;
  

  //必须要调用ngx_http_finalize_request
  ngx_http_finalize_request(r, ngx_http_send_header(r));

  return;
}

static void
ngx_http_get_param_value(ngx_log_t *log, char *body, char *key, ngx_str_t *value)
{
    char *start, *end;
    start = ngx_strstr(body, key);
    if (start) {
        start = start + ngx_strlen(key) + 1; //跳过'='
        end = ngx_strchr(start, '&');
        if (end) {
            value->len = end - start;
        } else {//表示最后一个参数
            value->len = body + strlen((const char*)body) - start;
        }    
        value->data = (u_char*)ngx_calloc(value->len+1, log);
        ngx_snprintf(value->data, value->len, "%s", start); 
    } else {
        value->len = 0;
        value->data = NULL;
    }
}


static char*
ngx_http_webservice_upload(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_webservice_upload_handler;
    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_webservice_upload_handler(ngx_http_request_t *r)
{
    if (r->method != NGX_HTTP_POST)
    {
        return NGX_HTTP_NOT_ALLOWED;
    }
    //异步接收body
    ngx_uint_t rc = ngx_http_read_client_request_body(r, ngx_http_webservice_upload_body_handler);
    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }
    return NGX_DONE;
}

static void 
ngx_http_webservice_upload_body_handler(ngx_http_request_t *r) 
{
    u_char* boundary = NULL;
    u_char* boundary_tmp = NULL;
    size_t boundary_len = 0;
    ngx_table_elt_t *content_type = 0;
    ngx_buf_t *buf = r->request_body->bufs->buf;
    ngx_uint_t i = 0;
    char *data = NULL;
    char file_name[256] = {0};
    char body[256] = {0};
    ngx_int_t uploadsize = 0; 
    FILE *file = NULL;
    
    
    //获取content_type
    content_type = r->headers_in.content_type;
    //判断是否存在boundary
    boundary_tmp = (u_char*)ngx_strstr(content_type->value.data, "boundary=");
    if (boundary_tmp == NULL) {
        goto fail403;
    }
    boundary_tmp += ngx_strlen("boundary=");//指向实际value
    // 第一个2 代表-- 第二个2代表最后\r\n
    boundary_len = content_type->value.data + content_type->value.len - boundary + 2 + 2;
    boundary = (u_char*)ngx_pcalloc(r->pool,  boundary_len + 1);//结束符
    ngx_snprintf(boundary, boundary_len, "--%s\r\n", boundary_tmp);

    //文件上传默认保存在临时文件中,因此需要对文件进行操作

    //解析fsize字段 代表上传文件大小
    file = fdopen(buf->file->fd, "r");
    fgets(body, sizeof(body), file);
    if (ngx_strcmp(body, boundary)) {//异常
        goto fail403;
    }

    fgets(body, sizeof(body), file);
    if (ngx_strstr(body, "name=\"fsize\"") == NULL) {
        goto fail403;
    }
    
    fgets(body, sizeof(body), file);
    if (ngx_strcmp(body, "\r\n")) {
        goto fail403;
    }
    fgets(body, sizeof(body), file);
    uploadsize = ngx_atoi((u_char*)body, ngx_strlen(body)-2);
    if (uploadsize == 0) {
        goto fail403;
    }
    
    fgets(body, sizeof(body), file);
    if (ngx_strcmp(body, boundary)) {//异常
        goto fail403;
    }
    
    // 获取文件名称        
    fgets(body, sizeof(body), file);
    data = ngx_strstr(body, "; filename=\"");
    if (data == NULL) {
        goto fail403;
    }    
    data += ngx_strlen("; filename=\"");
    while (data[i] != '\"') {
      file_name[i] = data[i];
      i++;
    }
    
    fgets(body, sizeof(body), file); //跳过Content-Type:
    fgets(body, sizeof(body), file); //跳过\r\n

    ngx_http_webservice_upload_writefile(r->pool, file, file_name, uploadsize);
    fclose(file);
    
    //由于不需要返回响应 只需要响应header即可 因此不需要设置output
       
    ngx_str_t response = ngx_string("[{\"Status\":\"Success\"}]");
    r->headers_out.content_length_n = response.len;
    ngx_str_t type = ngx_string("application/json");
    r->headers_out.content_type = type;
    r->headers_out.status = NGX_HTTP_OK;
    ngx_int_t rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
    {
        return ;
    }

    ngx_buf_t *b = ngx_create_temp_buf(r->pool, response.len);
    if (b == NULL)
    {
        return ;
    }
    ngx_memcpy(b->pos, response.data, response.len);
    b->last = b->pos + response.len;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;

    //必须要调用ngx_http_finalize_request
    ngx_http_finalize_request(r, ngx_http_output_filter(r, &out));
    return;
    
fail403:
    r->headers_out.status = NGX_HTTP_FORBIDDEN; 
    r->headers_out.content_length_n = 0;
    r->header_only = 1;        

    //必须要调用ngx_http_finalize_request
    ngx_http_finalize_request(r, ngx_http_send_header(r));
    return;
}

static void 
ngx_http_webservice_upload_writefile(ngx_pool_t *pool, FILE *file, const char* filename, size_t length) 
{
    FILE *wfile = 0;
    char path[256] = {0};
    char *buffer = NULL;
    buffer = ngx_palloc(pool, length);
    ngx_memcpy(path, "/usr/local/nginx/upload/", strlen("/usr/local/nginx/upload/"));
    ngx_memcpy(path + strlen(path), filename, ngx_strlen(filename));
    fread(buffer, length, 1, file);
    wfile = fopen(path, "w");
    fwrite(buffer, length, 1, wfile);
    fclose(wfile);
    return;
}

static char*
ngx_http_webservice_uploadlist(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_webservice_uploadlist_handler;
    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_webservice_uploadlist_handler(ngx_http_request_t *r)
{    
    ngx_buf_t *body = NULL;
    ngx_chain_t out;
    if (r->method != NGX_HTTP_GET)
    {
        return NGX_HTTP_NOT_ALLOWED;
    }
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK)
    {
        return rc;
    }
    DIR *dirptr = NULL;
    struct stat statbuf;
    struct dirent *entry;
    
    if((dirptr = opendir("/usr/local/nginx/upload"))==NULL)
    {
        printf("opendir failed!");
        return 1;
    }
    else
    {        
        body = ngx_create_temp_buf(r->pool, 1024);
        *body->start = '[';
        body->last = body->start+1; 
        chdir("/usr/local/nginx/upload");
        while ((entry = readdir(dirptr)))
        {
            stat(entry->d_name, &statbuf);
            if (S_ISDIR(statbuf.st_mode)) {
                continue;
            }
            body->last = ngx_sprintf(body->last, "{\"filename\":\"%s\",\"filesize\":\"%d\"},",
                        entry->d_name, statbuf.st_size);
            if (body->end - body->last < 256) {//可用空间小于256
               ngx_buf_t *new_body = ngx_create_temp_buf(r->pool, (body->end - body->start)+512);
               ngx_memcpy(new_body->start, body->start, body->last - body->pos);
               new_body->last = body->last;
               body = new_body;
            }
        }
        *(body->last-1) = ']';//逗号修改为]
        closedir(dirptr);
    }
    body->last_buf = 1;
    
    ngx_str_t type = ngx_string("application/json");
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_type = type;
    r->headers_out.content_length_n = body->last - body->pos;
    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
    {
        return rc;
    }
    
    out.buf = body;
    out.next = NULL;
    return ngx_http_output_filter(r, &out);
}


2.2 修改配置文件nginx.conf


user  root;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  debug;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        location /webui/upload/list {
            uploadlist;
        }
        location /webui/upload {
            upload;
        }        
        location /webui/messages {
            messages;
        }
        location /webui/messages/post {
            msgs_post;
        }
        location /webui/login {
            login;
        }
        location / {
            root   html;
            index  index.html index.htm;
        }

        #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   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

2.3 创建upload

由于实现了文件上传功能,因此需要创建一个目录用于保存文件,默认是/usr/local/nginx/upload

三、资源文件

为了方便大家学习,我将html页面以及webservice代码上传到csdn中,大家可以前去下载,积分很便宜只有1积分。欢迎大家一起探讨学习。

猜你喜欢

转载自blog.csdn.net/xxb249/article/details/84786822
今日推荐