美文网首页
基于nginx搭建简单的文件服务器

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

作者: Martain | 来源:发表于2020-05-18 22:08 被阅读0次

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

    前言

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

    环境

    • centos 7.6

    开始搭建

    下载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版本。

    • 官方地址

      官方版本存在比较大的bug,网上也有很多解决方案,比如这里,喜欢折腾的可以去尝试下;如果不想折腾请直接去已修复版本克隆下载下来使用。

      [root@localhost ~]# git clone https://github.com/martaintao/nginx-upload-module.git
      Cloning into 'nginx-upload-module'...
      remote: Enumerating objects: 32, done.
      remote: Total 32 (delta 0), reused 0 (delta 0), pack-reused 32
      Unpacking objects: 100% (32/32), done.
      [root@localhost ~]# ls
      anaconda-ks.cfg  nginx-1.16.1  nginx-1.16.1.tar.gz  nginx-upload-module
      [root@localhost ~]# 
      

      编译安装

    • 安装依赖库

      [root@localhost nginx-1.16.1]# yum install openssl-devel pcre-devel -y
      
    • 开始编译

      [root@localhost nginx-1.16.1]# ./configure --prefix=/usr/local/nginx --add-module=../nginx-upload-module --with-http_ssl_module
      
                                    ...
                                    
      configuring additional modules
      adding module in ../nginx-upload-module
       + ngx_http_upload_module was configured
      checking for PCRE library ... found
      checking for PCRE JIT support ... found
      checking for OpenSSL library ... found
      checking for zlib library ... found
      creating objs/Makefile
      
      Configuration summary
        + using system PCRE library
        + using system OpenSSL library
        + using system zlib library
      
        nginx path prefix: "/usr/local/nginx"
        nginx binary file: "/usr/local/nginx/sbin/nginx"
        nginx modules path: "/usr/local/nginx/modules"
        nginx configuration prefix: "/usr/local/nginx/conf"
        nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
        nginx pid file: "/usr/local/nginx/logs/nginx.pid"
        nginx error log file: "/usr/local/nginx/logs/error.log"
        nginx http access log file: "/usr/local/nginx/logs/access.log"
        nginx http client request body temporary files: "client_body_temp"
        nginx http proxy temporary files: "proxy_temp"
        nginx http fastcgi temporary files: "fastcgi_temp"
        nginx http uwsgi temporary files: "uwsgi_temp"
        nginx http scgi temporary files: "scgi_temp"
      
      [root@localhost nginx-1.16.1]# make & make install
      
    • 如果中途没有什么报错就说明编译安装成功了!

    编写配置文件

    前期准备

    因为需要实现上传下载功能,所以我们需要提前准备好相应的目录。这里我准备了两个目录:/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文件上传
    • 上传文件到/upload
    • nginx服务器接收到文件,先把文件保存到/var/www/tmp目录下,文件名为随机,但文件相关信息会转发给回调程序
    • 回调程序经过验证之后,返回文件信息。对于文件的处理根据具体需求来保存删除

    参数解释

    假如按照上面的配置的话,如果我们使用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

    • 使用python接收回调
    # 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()
    
    

    相关文章

      网友评论

          本文标题:基于nginx搭建简单的文件服务器

          本文链接:https://www.haomeiwen.com/subject/tphmohtx.html