开发一个基于nginx的上传功能。
下载nginx:https://nginx.org/en/download.html
nginx-1.18.0.tar.gz
下载nginx-upload-module插件:https://github.com/vkholodkov/nginx-upload-module/tags
nginx-upload-module-2.3.0.tar.gz
先解压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]#
yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
安装PCRE,让nginx支持Rewrite功能:
[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
./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
#! 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("错误的请求类型
", 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.conf
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; } }
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; } }
conf.d/nginxUplaod.conf
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
cd /usr/local/nginx
./sbin/nginx
nginx其它命令
./sbin/nginx -s reload ./sbin/nginx -s stop
启动python服务:
nohup python3 nginxUploadPassServer.py 1>nohup.out 2>&1 &
#! 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