基于nginx搭建简单的文件服务器

2020-05-18  本文已影响0人  Martain

基于nginx搭建简单的文件服务器

前言

​ 对于文件的上传和下载是目前的后端中及其常见的一种功能,我们可以使用私有云存储,例如阿里云、七牛云等,我们也可以直接写接口,保存上传的文件,返回已上传的文件。但是私有云存储需要一定的费用,自己写接口共用性又不高,而且需要写一堆雷同的业务逻辑,于是乎,最近我在寻找比较省力(主要是我懒)又省钱的方法来解决这个问题,然后我发现nginx可以使用模块来实现这个功能,以下就是我对这次实践的分享。

环境

开始搭建

下载nginx

[root@localhost ~]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@localhost ~]# ls
anaconda-ks.cfg  nginx-1.16.1.tar.gz
[root@localhost ~]# tar zxf nginx-1.16.1.tar.gz 
[root@localhost ~]# ls
anaconda-ks.cfg  nginx-1.16.1  nginx-1.16.1.tar.gz
[root@localhost ~]# 

下载nginx_upload_module

Nginx的服务由各个模块组成,nginx_upload_module模块用于接受并处理用户上传的文件,该模块最初的版本是十几年前的了,但是目前仍然才2.2.0版本。

编写配置文件

前期准备

因为需要实现上传下载功能,所以我们需要提前准备好相应的目录。这里我准备了两个目录:/var/www/tmp/var/www/resourcetmp目录为文件上传的临时目录,resource目录为实际存储和下载的目录。这里注意,我们需要保证两个目录的权限。

[root@localhost www]# pwd
/var/www
[root@localhost www]# ll
total 0
drwxrwxrwx. 2 root root 6 May 18 08:10 resource
drwxrwxrwx. 2 root root 6 May 18 08:10 tmp
[root@localhost www]# 

配置nginx

这里主要是关于上传的配置,因为下载非常简单。

server {
    listen       80;
    server_name  localhost; 
    #文件下载配置
    location /download {
            # 这里设置下载的文件目录
            alias /var/www/resource;
            #是否打开目录结构(视情况是否打开),即直接访问xxx.com/download是否需要显示出文件目录结构
            autoindex on;
    }
    #文件上传相关配置      
    location /upload {
            # 配置文件上传大小
            client_max_body_size 50m;
            # 转到后台处理URL 
            upload_pass @uploadhandle;
            # 临时保存路径 (暂时保存此处,使用回调处理,将临时文件变成真实有效文件)
            # 可以使用散列
            upload_store /var/www/tmp;
            upload_pass_args on;
            # 上传文件的权限,rw表示读写 r只读 
            upload_store_access user:rw;
            # 这里写入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 "^submit$|^description$";
            upload_pass_form_field "^.*$";
            # 每秒字节速度控制,0表示不受控制,默认0 
            upload_limit_rate 0;
            # 如果pass页面是以下状态码,就删除此次上传的临时文件 
            upload_cleanup 400 404 499 500-505;                                                                                
    }
    # upload_pass 不支持uri添加/(可以使用alias)     
    location @uploadhandle { 
            #下面这个配置等同于访问:http://localhost:9999/upload,这里暂时不做演示
        # proxy_pass  http://localhost:9999; 
        return 200; # 如果不需要后台处理,可以直接返回200
    } 
}

上传原理

nginx文件上传

参数解释

假如按照上面的配置的话,如果我们使用formData传一个键值为test的文件upload.conf到服务器。

其中,服务器获取到之后,配置中的upload_field_name就是键值名test.回调程序获取到的转发的form里面是这样的:

​ 'test_name':'upload.conf',

​ 'test_content_type':'text/plain',

​ 'test_path',:'/var/www/tmp/0000000012',

​ 'test_md5':'115abcb34ef9c1ff1191bb63b1ef15a9',

​ 'test_size', '1396'

回调程序

网上许多人使用Lua开发回调程序,我们也可以使用任何一种后端语言来实现回调程序,由于时间原因,后面在分享我一个回调程序的实例...o(╥﹏╥)o

# encoding=utf8
from flask import Flask, request, jsonify
from gevent import pywsgi
from flask_cors import CORS
import shutil
import os
import time

app = Flask(__name__)
app.debug = True
app.config['JSON_AS_ASCII'] = False
CORS(app, supports_credentials=True)

download_path_prefix = "/var/www/download"


@app.route("/upload", methods=["GET", "POST", "OPTIONS", "PUT", "DELETE"])
def hello():
    file_name = request.form["file_name"]
    file_content_type = request.form["file_content_type"]
    file_path = request.form["file_path"]
    file_md5 = request.form["file_md5"]
    file_size = request.form["file_size"]
    save_file_name = str(int(time.time()))+"-"+file_name
    shutil.move(file_path, os.path.join(download_path_prefix,save_file_name))
    res = {
        "uploadFileName":file_name,
        "fileContentType":file_content_type,
        "fileSize":file_size,
        "fileUrl":"http://x.x.x.x/download/"+save_file_name
    }
    return success_with_data(res)


def success():
    return response(0, "success")


def success_with_data(data):
    return response(0, "success", data)


def fail(msg):
    return response(-1, msg)


def response(status, msg, data=''):
    return jsonify({'status': status, 'msg': msg, 'data': data})

if __name__ == "__main__":
    server = pywsgi.WSGIServer(('0.0.0.0', 9999), app)
    server.serve_forever()

上一篇下一篇

猜你喜欢

热点阅读