1. 程式人生 > >使用Nginx Upload Module實現上傳檔案功能

使用Nginx Upload Module實現上傳檔案功能

普通網站在實現檔案上傳功能的時候,一般是使用Python,Java等後端程式實現,比較麻煩。Nginx有一個Upload模組,可以非常簡單的實現檔案上傳功能。此模組的原理是先把使用者上傳的檔案儲存到臨時檔案,然後在交由後臺頁面處理,並且把檔案的原名,上傳後的名稱,檔案型別,檔案大小set到頁面。下面和大傢俱體介紹一下。

一、編譯安裝Nginx

為了使用Nginx Upload Module,需要編譯安裝Nginx,將upload module編譯進去。upload module的程式碼可以去Github上下載:Upload Module
之後的編譯安裝Nginx這裡就不介紹,不瞭解的可以參考:Ubuntu 14.10下原始碼編譯安裝Nginx 1.8.0

二、Nginx配置

Nginx upload module的簡單配置如下:
server {
    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即可 } }

三、後端處理程式

這裡我們使用Django作為後端處理程式,比較簡單,具體如下:
首先建立Django專案:
django-admin.py startproject uploadmodule
然後,建立views.py檔案,程式碼如下:
# -*- 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

四、示例

上面的程式碼完成之後,我們通過下面的命令啟動Django後端程式:
cd uploadmodule/
python manage.py runserver 0.0.0.0:9999
然後,模擬POST請求:http://192.168.1.251/upload/,上傳一個jpg檔案,返回結果如下:
{
    "name": "6125444419718417450.jpg",
    "ip": "192.168.1.121",
    "content_type": "image/jpeg",
    "path": "/tmp/nginx_upload/0000000002",
    "md5": "c3b1bd2e72694a8d5fc4548b9ecd9e18",
    "size": "37980"
}

參考:
Ubuntu 14.10下原始碼編譯安裝Nginx 1.8.0
HttpUploadModule - Nginx Community
vkholodkov/nginx-upload-module at 2.2
Uploading to nginx using the nginx upload module with php_handler

Over!