天天看點

nginx upload子產品+python 後端處理模仿fastdfs實作檔案存取

前提條件:

1.編譯安裝帶有nginx upload 子產品的nginx,安裝腳本如下。

2.配置nginx的conf檔案,一個server配置upload上傳,一個server配置download下載下傳

3.使用django快速部署python後端服務,對nginx存入的檔案進行處理,并傳回下載下傳的url

注釋:如果不适用後端處理,nginx也可以實作将檔案上傳,但是由于upload子產品将檔案存入時會自己命名存入,無法記錄相關檔案類型。如果直接從nginx存儲目錄下載下傳,會導緻檔案的字尾丢失,無法擷取檔案類型。

####nginx安裝腳本

[[email protected] ~]# cat autonginx 
#!/bin/bash
#install nginx/1.10.3

#Installation path
INSTALL_DIR=/usr/local/
SRC_DIR=/opt/package

[ ! -d ${INSTALL_DIR} ] && mkdir -p ${INSTALL_DIR}
[ ! -d ${SRC_DIR} ] && mkdir -p ${SRC_DIR}

# Check if user is root
if [ $(id -u) != "0" ]; then
    echo "Error: You must be root to run this script!!"
    exit 
fi

#Install dependency package
for Package in wget gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre pcre-devel unzip
do
    yum -y install $Package
done

function  Install_Nginx()
{
#update version
NGINX="nginx-1.10.3"
PCRE="pcre-8.40"
ZLIB="zlib-1.2.11"
OPENSSL="openssl-1.1.0e"
PURGE="ngx_cache_purge-2.3"
UPLOAD="nginx-upload-module-2.2"

NGINXFEATURES="--prefix=${INSTALL_DIR}nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-stream \
--with-stream_ssl_module \
--pid-path=/var/run/nginx.pid \
--with-pcre=${SRC_DIR}/${PCRE} \
--with-zlib=${SRC_DIR}/${ZLIB} \
--with-openssl=${SRC_DIR}/${OPENSSL} \
--add-module=${SRC_DIR}/${PURGE} \
--add-module=${SRC_DIR}/${UPLOAD}
"

cd ${SRC_DIR}
#download package
echo 'Downloading NGINX'
if [ ! -f ${NGINX}.tar.gz ]
then
  wget -c http://nginx.org/download/${NGINX}.tar.gz
else
  echo 'Skipping: NGINX already downloaded'
fi

echo 'Downloading PCRE'
if [ ! -f ${PCRE}.tar.gz ]
then
  wget -c https://ftp.pcre.org/pub/pcre/${PCRE}.tar.gz     
else
  echo 'Skipping: PCRE already downloaded'
fi

echo 'Downloading ZLIB'
if [ ! -f ${ZLIB}.tar.gz ]
then
  wget -c http://zlib.net/${ZLIB}.tar.gz
else
  echo 'Skipping: ZLIB already downloaded'
fi

echo 'Downloading OPENSSL'
if [ ! -f ${OPENSSL}.tar.gz ]
then
  wget -c http://www.openssl.org/source/${OPENSSL}.tar.gz
else
  echo 'Skipping: OPENSSL already downloaded'
fi

echo 'Downloading PURGE'

if [ ! -f .tar.gz ]
then
   wget -c https://github.com//FRiCKLE/ngx_cache_purge/archive/.tar.gz
else
   echo 'Skipping: PURGE already downloaded'
fi



if [ ! -f  ]
then
   wget -c  https://codeload.github.com/vkholodkov/nginx-upload-module/zip/
else
   echo 'Skipping: nginx-upload-module already downloaded'
fi



echo '----------Unpacking downloaded archives. This process may take serveral minutes---------'

echo "Extracting ${NGINX}..."
tar xzf ${NGINX}.tar.gz
echo 'Done.'

echo "Extracting ${PCRE}..."
tar xzf ${PCRE}.tar.gz
echo 'Done.'

echo "Extracting ${ZLIB}..."
tar xzf ${ZLIB}.tar.gz
echo 'Done.'

echo "Extracting ${OPENSSL}..."
tar xzf ${OPENSSL}.tar.gz
echo 'Done.'

echo "Extracting ${PURGE}..."
tar xzf .tar.gz
echo 'Done.'


echo "Extracting ${UPLOAD}..."
unzip 
echo 'Done.'


#add new user
groupadd -r nginx
useradd -r -g nginx nginx

#make
echo '###################'
echo 'Compile NGINX'
echo '###################'
cd ${SRC_DIR}/${NGINX}
./configure ${NGINXFEATURES}
make
make install
echo '###################'
echo 'ok'
echo '###################'
}

Install_Nginx
           

在此前,建立/www/web/upload/tmp目錄。然後配置一下内容重新開機nginx。

####nginx配置檔案


#####upload所需要的server


server {
    listen ;

    client_max_body_size m;
    client_body_buffer_size k;
    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;


    error_page  = @405;

        location / {
            index index.html index.htm index.php;
        }

        location @405
        {
            root /www/web/upload;
        }


    location /upload {
        # 轉到背景處理URL,表示Nginx接收完上傳的檔案後,然後交給後端處理的位址
        upload_pass @python;

        # 臨時儲存路徑, 可以使用散列
        # 上傳子產品接收到的檔案臨時存放的路徑, 1 表示方式,該方式是需要在/tmp/nginx_upload下建立以0到9為目錄名稱的目錄,上傳時候會進行一個散列處理。
        upload_store /www/web/upload/tmp ;

        # 上傳檔案的權限,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 ;

        # 如果pass頁面是以下狀态碼,就删除此次上傳的臨時檔案
        upload_cleanup    -;

        # 打開開關,意思就是把前端腳本請求的參數會傳給後端的腳本語言,比如:http://192.168.1.251:9000/upload/?k=23,背景可以通過POST['k']來通路。
        upload_pass_args on;
    }

    location @python {
        proxy_pass http://localhost:;
        # return 200;  # 如果不需要後端程式處理,直接傳回200即可
    }
}


#######download所需要的server#############


 server {
        listen ;
        root /tmp/nginx_upload/;
        location /nginx_upload {
                root /tmp;

        }

     }
           

此刻,你已經完成了nginx的配置,可以使用小程式進行一下上傳測試,看看nginx是否可以上傳檔案。

import requests


file_dir = 'images/logo.png'
file = open(file_dir, 'rb')
files = {'attachment_file': (file_dir, file, 'image/png', {})}
r1 = requests.post('http://172.18.3.183:99/upload', files=files)
print(r1.text)
file.close()
           

通過python模拟post請求,将圖檔上傳到剛才nginx開放的接口,然後在剛才建立的目錄查找檔案

接下來,進行後端伺服器的部署,可以使用django進行部署。

1.pip install Django==1.8.9

2. django-admin.py startproject UPload

3. cd UPload/

4. python manage.py startapp file_parse

5. cd file_parse

6. 将下面的view.py添加到view.py中

7. 在settings.py中添加file_parse

8. 在url.py中添加 url(r’^upload’,file_parse_views.upload),

9. python manage.py runserver 0.0.0.0:9999

#django中的view.py

import os
import json
import time


from django.views.decorators.csrf import csrf_exempt

date = time.strftime('%Y%m%d')
UPLOAD_FILE_PATH = '/tmp/nginx_upload/%s/' %date
isExists=os.path.exists(UPLOAD_FILE_PATH)
if not isExists:
         os.makedirs(UPLOAD_FILE_PATH)
else:
        print('path isexist!')


from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.


def index(request):
    return HttpResponse("Hello Django!")

@csrf_exempt
def upload(request):
    request_params = request.POST
    print(request_params)
    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,file_name)
    new_file_path = ''.join([UPLOAD_FILE_PATH, new_file_name])
    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,
    })

    print(new_file_path)
    path_dir = new_file_path.split('/')[:]
    res = '/'.join(path_dir)
    download_url = '/'.join(('http://172.18.3.183:88',res))

    response = HttpResponse(download_url, content_type='application/json; charset=utf-8')


    return response
           

實作效果圖:

nginx upload子產品+python 後端處理模仿fastdfs實作檔案存取