| 后一修订版 | 前一修订版 | ||
|
服务器技术:nginx:使用_nginx_upload_module_实现上传文件功能 [2018/09/04 15:49] admin 创建 |
服务器技术:nginx:使用_nginx_upload_module_实现上传文件功能 [2018/09/10 18:02] (当前版本) |
||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | <p>普通网站在实现文件上传功能的时候,一般是使用Python,Java等后端程序实现,比较麻烦。Nginx有一个Upload模块,可以非常简单的实现文件上传功能。此模块的原理是先把用户上传的文件保存到临时文件,然后在交由后台页面处理,并且把文件的原名,上传后的名称,文件类型,文件大小set到页面。下面和大家具体介绍一下。</p><h4>一、编译安装Nginx</h4><p>为了使用Nginx Upload Module,需要编译安装Nginx,将upload module编译进去。upload module的代码可以去Github上下载: <a title="Upload Module" href="https://github.com/vkholodkov/nginx-upload-module/tree/2.2" target="_blank">Upload Module</a></p><p>之后的编译安装Nginx这里就不介绍,不了解的可以参考: <a title="Ubuntu 14.10下源码编译安装Nginx 1.8.0" href="http://www.bkjia.com/Linux/1002916.html" target="_blank">Ubuntu 14.10下源码编译安装Nginx 1.8.0</a></p><h4>二、Nginx配置</h4><p>Nginx upload module的简单配置如下:</p><pre class="prettyprint">server { | + | 普通网站在实现文件上传功能的时候,一般是使用Python,Java等后端程序实现,比较麻烦。Nginx有一个Upload模块,可以非常简单的实现文件上传功能。此模块的原理是先把用户上传的文件保存到临时文件,然后在交由后台页面处理,并且把文件的原名,上传后的名称,文件类型,文件大小set到页面。下面和大家具体介绍一下。<br/>一、编译安装Nginx<br/><br/>为了使用Nginx Upload Module,需要编译安装Nginx,将upload module编译进去。upload module的代码可以去Github上下载: Upload Module<br/><br/>之后的编译安装Nginx这里就不介绍,不了解的可以参考: Ubuntu 14.10下源码编译安装Nginx 1.8.0<br/>二、Nginx配置<br/><br/>Nginx upload module的简单配置如下:<br/><br/>server {<br/>    listen *:80 default_server;<br/>    server_name 192.168.1.251;<br/>    client_max_body_size 20m;<br/>    client_body_buffer_size 512k;<br/>    proxy_set_header Host $host;<br/>    proxy_set_header X-Real-IP $remote_addr;<br/>    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br/>    proxy_set_header REMOTE_ADD $remote_addr;<br/>    location /upload {<br/>   # 转到后台处理URL,表示Nginx接收完上传的文件后,然后交给后端处理的地址<br/>  upload_pass @python;<br/>  # 临时保存路径, 可以使用散列<br/>  # 上传模块接收到的文件临时存放的路径, 1 表示方式,该方式是需要在/tmp/nginx_upload下创建以0到9为目录名称的目录,上传时候会进行一个散列处理。<br/>  upload_store /tmp/nginx_upload;<br/>  # 上传文件的权限,rw表示读写 r只读<br/>   upload_store_access user:rw group:rw all:rw;<br/>    set $upload_field_name "file";<br/>   # upload_resumable on;<br/>  # 这里写入http报头,pass到后台页面后能获取这里set的报头字段<br/>  upload_set_form_field "${upload_field_name}_name" $upload_file_name;<br/> upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;<br/> upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;<br/> # Upload模块自动生成的一些信息,如文件大小与文件md5值<br/>  upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;<br/> upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;<br/> # 允许的字段,允许全部可以 "^.*$"<br/>  upload_pass_form_field "^.*$";<br/>   # upload_pass_form_field "^submit$|^description$";<br/>  # 每秒字节速度控制,0表示不受控制,默认0, 128K<br/>    upload_limit_rate 0;<br/>  # 如果pass页面是以下状态码,就删除此次上传的临时文件<br/>   upload_cleanup 400 404 499 500-505;<br/>  # 打开开关,意思就是把前端脚本请求的参数会传给后端的脚本语言,比如:http://192.168.1.251:9000/upload/?k=23,后台可以通过POST['k']来访问。<br/>   upload_pass_args on; <br/>    }<br/>    location @python {<br/>   proxy_pass http://localhost:9999;<br/>    # return 200;  # 如果不需要后端程序处理,直接返回200即可<br/>    }<br/>}<br/><br/>三、后端处理程序<br/><br/>这里我们使用Django作为后端处理程序,比较简单,具体如下:<br/><br/>首先创建Django项目:<br/><br/>django-admin.py startproject uploadmodule<br/><br/>然后,创建views.py文件,代码如下:<br/><br/># -*- coding: utf-8 -*-<br/>import os<br/>import json<br/>from django.http import HttpResponse<br/>from django.views.decorators.csrf import csrf_exempt<br/>UPLOAD_FILE_PATH = '/tmp/nginx_upload/'<br/>@csrf_exempt<br/>def upload(request):<br/>    request_params = request.POST<br/>    file_name = request_params['file_name']<br/>    file_content_type = request_params['file_content_type']<br/>    file_md5 = request_params['file_md5']<br/>    file_path = request_params['file_path']<br/>    file_size = request_params['file_size']<br/>    ip_address = request.META.get('HTTP_X_REAL_IP') or request.META.get('HTTP_REMOTE_ADD')<br/>   # save file to tmp<br/>   new_file_name = '%s_%s' % (file_md5, ip_address)<br/>   new_file_path = ''.join([UPLOAD_FILE_PATH, new_file_name, os.path.splitext(file_name)[-1]])<br/>  with open(new_file_path, 'a') as new_file:<br/>       with open(file_path, 'rb') as f:<br/>           new_file.write(f.read())<br/>    content = json.dumps({<br/>       'name': file_name,<br/>        'content_type': file_content_type,<br/>        'md5': file_md5,<br/>        'path': file_path,<br/>        'size': file_size,<br/>        'ip': ip_address,<br/>    })<br/>    response = HttpResponse(content, content_type='application/json; charset=utf-8')<br/>  return response<br/><br/>四、示例<br/><br/>上面的代码完成之后,我们通过下面的命令启动Django后端程序:<br/><br/>cd uploadmodule/<br/>python manage.py runserver 0.0.0.0:9999<br/><br/>然后,模拟POST请求:http://192.168.1.251/upload/,上传一个jpg文件,返回结果如下:<br/><br/>{<br/>   "name": "6125444419718417450.jpg",<br/>   "ip": "192.168.1.121",<br/>   "content_type": "image/jpeg",<br/>   "path": "/tmp/nginx_upload/0000000002",<br/>   "md5": "c3b1bd2e72694a8d5fc4548b9ecd9e18",<br/>   "size": "37980"<br/>}<br/><br/> |
| - |    listen *:80 default_server; | + | |
| - |    server_name 192.168.1.251; | + | |
| - |    client_max_body_size 20m; | + | |
| - |    client_body_buffer_size 512k; | + | |
| - |    proxy_set_header Host $host; | + | |
| - |    proxy_set_header X-Real-IP $remote_addr; | + | |
| - |    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | + | |
| - |    proxy_set_header REMOTE_ADD $remote_addr; | + | |
| - |    location /upload { | + | |
| - | # 转到后台处理URL,表示Nginx接收完上传的文件后,然后交给后端处理的地址 | + | |
| - | upload_pass @python; | + | |
| - | # 临时保存路径, 可以使用散列 | + | |
| - | # 上传模块接收到的文件临时存放的路径, 1 表示方式,该方式是需要在/tmp/nginx_upload下创建以0到9为目录名称的目录,上传时候会进行一个散列处理。 | + | |
| - | upload_store /tmp/nginx_upload; | + | |
| - | # 上传文件的权限,rw表示读写 r只读 | + | |
| - | upload_store_access user:rw group:rw all:rw; | + | |
| - | set $upload_field_name "file"; | + | |
| - | # upload_resumable on; | + | |
| - | # 这里写入http报头,pass到后台页面后能获取这里set的报头字段 | + | |
| - | 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; | + | |
| - | # Upload模块自动生成的一些信息,如文件大小与文件md5值 | + | |
| - | 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 "^.*$"; | + | |
| - | # upload_pass_form_field "^submit$|^description$"; | + | |
| - | # 每秒字节速度控制,0表示不受控制,默认0, 128K | + | |
| - | upload_limit_rate 0; | + | |
| - | # 如果pass页面是以下状态码,就删除此次上传的临时文件 | + | |
| - | upload_cleanup 400 404 499 500-505; | + | |
| - | # 打开开关,意思就是把前端脚本请求的参数会传给后端的脚本语言,比如:http://192.168.1.251:9000/upload/?k=23,后台可以通过POST['k']来访问。 | + | |
| - | upload_pass_args on;   | + | |
| - |     } | + | |
| - |    location @python { | + | |
| - | proxy_pass http://localhost:9999; | + | |
| - | # return 200;  # 如果不需要后端程序处理,直接返回200即可 | + | |
| - |    } | + | |
| - | }</pre><h4>三、后端处理程序</h4><p>这里我们使用Django作为后端处理程序,比较简单,具体如下:</p><p>首先创建Django项目:</p><pre>django-admin.py startproject uploadmodule</pre><p>然后,创建views.py文件,代码如下:</p><pre class="prettyprint"># -*- coding: utf-8 -*- | + | |
| - | import os | + | |
| - | import json | + | |
| - | from django.http import HttpResponse | + | |
| - | from django.views.decorators.csrf import csrf_exempt | + | |
| - | UPLOAD_FILE_PATH = '/tmp/nginx_upload/' | + | |
| - | @csrf_exempt | + | |
| - | def upload(request): | + | |
| - | request_params = request.POST | + | |
| - | file_name = request_params['file_name'] | + | |
| - | file_content_type = request_params['file_content_type'] | + | |
| - | file_md5 = request_params['file_md5'] | + | |
| - | file_path = request_params['file_path'] | + | |
| - | file_size = request_params['file_size'] | + | |
| - | ip_address = request.META.get('HTTP_X_REAL_IP') or request.META.get('HTTP_REMOTE_ADD') | + | |
| - | # save file to tmp | + | |
| - | new_file_name = '%s_%s' % (file_md5, ip_address) | + | |
| - | new_file_path = ''.join([UPLOAD_FILE_PATH, new_file_name, os.path.splitext(file_name)[-1]]) | + | |
| - | with open(new_file_path, 'a') as new_file: | + | |
| - | with open(file_path, 'rb') as f: | + | |
| - | new_file.write(f.read()) | + | |
| - | content = json.dumps({ | + | |
| - | 'name': file_name, | + | |
| - | 'content_type': file_content_type, | + | |
| - | 'md5': file_md5, | + | |
| - | 'path': file_path, | + | |
| - | 'size': file_size, | + | |
| - | 'ip': ip_address, | + | |
| - | }) | + | |
| - | response = HttpResponse(content, content_type='application/json; charset=utf-8') | + | |
| - | return response</pre><h4>四、示例</h4><p>上面的代码完成之后,我们通过下面的命令启动Django后端程序:</p><pre>cd uploadmodule/ | + | |
| - | python manage.py runserver 0.0.0.0:9999</pre><p>然后,模拟POST请求:http://192.168.1.251/upload/,上传一个jpg文件,返回结果如下:</p><pre class="prettyprint">{ | + | |
| - | "name": "6125444419718417450.jpg", | + | |
| - | "ip": "192.168.1.121", | + | |
| - | "content_type": "image/jpeg", | + | |
| - | "path": "/tmp/nginx_upload/0000000002", | + | |
| - | "md5": "c3b1bd2e72694a8d5fc4548b9ecd9e18", | + | |
| - | "size": "37980" | + | |
| - | }</pre><p><br/></p> | + | |