搭建:基于nginx的上传功能

搭建:基于nginx的上传功能

文章目录

一、准备

开发一个基于nginx的上传功能。

二、安装nginx

1.1 解压nginx和nginx插件

先解压nginx-1.18.0.tar.gz, 然后将nginx-upload-module-2.3.0.tar.gz解压到nginx-1.18.0目录下。

复制代码
[root@VM-4-3-centos nginx-1.18.0]# ll
总用量 788
drwxr-xr-x 6 1001 1001   4096 8月  19 09:52 auto
-rw-r--r-- 1 1001 1001 302863 4月  21 2020 CHANGES
-rw-r--r-- 1 1001 1001 462213 4月  21 2020 CHANGES.ru
drwxr-xr-x 2 1001 1001   4096 8月  19 09:52 conf
-rwxr-xr-x 1 1001 1001   2502 4月  21 2020 configure
drwxr-xr-x 4 1001 1001   4096 8月  19 09:52 contrib
drwxr-xr-x 2 1001 1001   4096 8月  19 09:52 html
-rw-r--r-- 1 1001 1001   1397 4月  21 2020 LICENSE
drwxr-xr-x 2 1001 1001   4096 8月  19 09:52 man
drwxrwxr-x 3 root root   4096 8月   2 2018 nginx-upload-module-2.3.0
-rw-r--r-- 1 1001 1001     49 4月  21 2020 README
drwxr-xr-x 9 1001 1001   4096 8月  19 09:52 src
[root@VM-4-3-centos nginx-1.18.0]#

1.2 编译并安装nginx

shell 复制代码
yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel

安装PCRE,让nginx支持Rewrite功能:

shell 复制代码
[root@VM-4-3-centos servers]# cd pcre-8.35/
[root@VM-4-3-centos pcre-8.35]# ./configure
[root@VM-4-3-centos pcre-8.35]# make && make install
......
[root@VM-4-3-centos pcre-8.35]# pcre-config --version
8.35
[root@VM-4-3-centos pcre-8.35]#

编译并安装nginx

mkdir /usr/local/nginx

shell 复制代码
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --add-module=./nginx-upload-module-2.3.0 --with-pcre=/data/dev/servers/pcre-8.35

make && make install

三、启动一个python后台服务,用于上传到临时路径文件,转移到正式路径

python 复制代码
#! python3
# -*- coding: UTF-8 -*-
###########################
#
# description: nginx上传文件,将临时路径的文件拷贝到正式路径
# author: LiFei  
# mail: hefrankeleyn@gmail.com
# date: 2023-08-19
#  pip install Flask
#
###########################

import logging,os,datetime, shutil, json,socket
from flask import Flask,request,abort,make_response
logging.basicConfig(level=logging.INFO, format="%(asctime)s- %(name)s %(levelname)s- %(message)s")
# 创建一个应用
app = Flask(__name__)
base_dir="/data/dev/nginxUploadFiles"

# 创建目录,如果目录不存在
def createDirIfNotExists(dirPath):
    if not dirPath:
        return
    if not (os.path.exists(dirPath) and os.path.isdir(dirPath)):
        os.makedirs(dirPath)

# 创建子路径
def createSubDir(params):
    sub_file_dir = ""
    if "busType" in params:
        busType = str(params["busType"]).replace(' ', '')
    if busType:
        sub_file_dir = os.path.join(sub_file_dir, busType)
    one_day = datetime.datetime.now().strftime('%Y%m%d')
    sub_file_dir = os.path.join(sub_file_dir, one_day)
    createDirIfNotExists(os.path.join(base_dir, sub_file_dir))
    return sub_file_dir


# 将临时文件拷贝到正式文件目录
def exeUpload(params):
    if not params:
        abort(400)
    bus_file_name = params["file.name"]
    file_type = params["file.content_type"]
    tmp_file_path = params["file.path"]
    file_md5 = params["file.md5"]
    file_size = params["file.size"]
    real_filename = file_md5 + (bus_file_name[bus_file_name.rfind("."):] if bus_file_name.rfind(".")!=-1 else "")
    subDirPath = createSubDir(params)
    target_file_path = os.path.join(base_dir, subDirPath, real_filename)
    # 将临时路径文件拷贝到正式路径
    shutil.copyfile(tmp_file_path, target_file_path)
    # 这个路径,可以访问正式目录下的文件
    base_url = "http://%s:8088/" % (socket.gethostbyname(socket.gethostname()))
    # 返回结果
    json_data = json.dumps({
        "file_name": bus_file_name,
        "content_type": file_type,
        "file_md5": file_md5,
        "file_size": file_size,
        "file_path": target_file_path,
        "base_url": base_url,
        "sub_file_path": os.path.join(subDirPath, real_filename)
    })
    response = make_response(json_data)
    headers = {
        "content-type": "application/json; charset=utf-8"
    }
    response.headers = headers
    return response

@app.route("/upload", methods=["POST", 'GET'])
def nginxUpload():
    if request.method == "POST":
        try:
            params = request.form.to_dict()
            response = exeUpload(params)
            return response
        except Exception as e:
            err_str = str(e)
            response = make_response(err_str, 500)
            headers = {
                "content-type": "text/plain; charset=utf-8"
            }
            response.headers = headers
            return response
    else:
        response = make_response("<p>错误的请求类型</p>", 500)
        headers = {
            "content-type": "text/plain; charset=utf-8"
        }
        response.headers = headers
        return response

if __name__ =="__main__":
    app.run(host="0.0.0.0", port=2230)

启动服务:

nohup python3 nginxUploadPassServer.py 1>nohup.out 2>&1 &

四、添加nginx配置

nginx.conf

shell 复制代码
user root;
worker_processes  1;

events {
    worker_connections  1024;
}

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

    sendfile        on;

    keepalive_timeout  65;

    include /usr/local/nginx/conf/conf.d/*.conf;
}

conf.d/nginx_80.conf

复制代码
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

(1)配置一个静态文件服务

conf.d/nginx_80.conf

复制代码
    server {
        listen       8088;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            alias  /data/dev/nginxUploadFiles/;
            autoindex on;
            #root   html;
            #index  index.html index.htm;
        }

   }

(2)配置上传文件服务

conf.d/nginxUplaod.conf

shell 复制代码
server {
   listen 5312;
   client_max_body_size 100m;
   
   location /upload {
       # 转到后端处理的URL,表示Nginx接受完上传的文件后,然后交给后端处理的地址
       upload_pass @fileserver_backend;
       # 上传模块接收到文件,临时存放的路径,1 表示方法,该方法需要在/tmp/nginx_upload 下创建以0 到 9位目录,上传的时候会进行一散列处理。 mkdir -p /tmp/nginx_upload/{0,1,2,3,4,5,6,7,8,9}; chmod 777 -R /tmp/nginx_upload
       upload_store /tmp/nginx_upload 1;
       # 上传文件的权限,rw表示读写,r只读
       upload_store_access user:rw group:rw all:rw;
       set $upload_field_name "file";
       # 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 模块自动生成一些信息,如文件大小,文件的md值
       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$";
       # 如果pass页面出现以下状态码,就删除本次上传的临时文件
       upload_cleanup 400 404 499 500-505;
       # 打开开关, 把前段脚本请求的参数传给后端的脚本语言
       upload_pass_args on;
   }
   
   location @fileserver_backend {
      proxy_pass http://localhost:2230;
   }
}

五、启动nginx和python服务

启动nginx

cd /usr/local/nginx

./sbin/nginx

nginx其它命令

shell 复制代码
./sbin/nginx -s reload
./sbin/nginx -s stop

启动python服务:

复制代码
nohup python3 nginxUploadPassServer.py 1>nohup.out 2>&1 &

六、python程序测试上传

python 复制代码
#! python3
# -*- coding: UTF-8 -*-
###########################
#
# description: 执行上传
# author: LiFei  
# mail: hefrankeleyn@gmail.com
# date: 2023-08-19
#
###########################
import logging, os, requests
logging.basicConfig(level=logging.INFO, format="%(asctime)s- %(name)s %(levelname)s- %(message)s")


def uploadFile(upload_url, file_path, content_type):
    try:
        if not (os.path.exists(file_path) and os.path.isfile(file_path)):
            raise Exception("要上传的文件不存在:" + str(file_path))
        data = {
            "busType": "myPro"
        }
        fileName = os.path.split(file_path)[-1]
        files = {
            "file": (fileName, open(file_path, 'rb'), content_type)
        }
        response = requests.post(upload_url, files=files, data=data)
        return response
    except Exception as e:
        logging.error(e)
        raise e


if __name__=="__main__":
    upload_url = "http://myip:5312/upload"
    file_path = r"/Users/lifei/Documents/workspace/git_test_wp/myproject/wuyishan.jpg"
    content_type = "image/jpeg"
    response = uploadFile(upload_url, file_path, content_type)
    logging.info(response.json())

之后就可以访问到:

http://myip:8088/myPro/20230819/cad0d40e01e0930cad9030f8cc32f68b.jpg

相关推荐
乘云数字DATABUFF4 天前
5分钟部署开源APM Databuff:OpenTelemetry全链路追踪入门实战
运维·后端
荣--6 天前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森6 天前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜7 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB8 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode9 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户03284722207010 天前
如何搭建本地yum源(上)
运维
ping某11 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
大树8813 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠13 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql