栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

容器中使用ngnix搭建支持上传下载的文件服务器

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

容器中使用ngnix搭建支持上传下载的文件服务器

一、安装nginx容器

为了让nginx支持文件上传,需要下载并运行带有nginx-upload-module模块的容器:

sudo podman pull docker.io/dimka2014/nginx-upload-with-progress-modules:latest
sudo podman -d --name nginx -p 83:80 docker.io/dimka2014/nginx-upload-with-progress-modules

该容器同时带有nginx-upload-module模块和nginx-upload-progress-module模块。

注意该容器是Alpine Linux ,没有bash,有些命令与其它发行版本的Linux不一样。

使用下面的命令进入容器:

sudo podman exec -it nginx /bin/sh

作为文件服务器, 需要显示本地时间,默认不是本地时间。通过下面一系列命令设置为本地时间:

apk update
apk add tzdata
echo "Asia/Shanghai" > /etc/timezone
rm -rf /etc/localtime
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
apk del tzdata

创建文件服务器的根目录:

mkdir -p /nginx/share
二、配置nginx

配置文件的路径为/etc/nginx/conf.d/default.conf,作为

server {
    ……
    charset utf-8; # 设置字符编码,避免中文乱码
    location / {
            root   /nginx/share; # 根目录
            autoindex   on;  # 开启索引功能
            autoindex_exact_size off; # 关闭计算文件确切大小(单位bytes),只显示大概大小(单位kb、mb、gb)
            autoindex_localtime on; # 显示本地时间
        }
}

此时我们的文件服务就配置好了,需要使用下面的命令让配置生效:

nginx -s reload

三、支持文件上传 1. 配置nginx

上面的配置已经完成文件服务器的配置了,但是不能上传文件,想要上传文件,还需要做如下配置:

server {
    ……
    charset utf-8; # 设置字符编码,避免中文乱码
    client_max_body_size 32m; 
    upload_limit_rate 1M; # 限制上传速度最大1M
    
    # 设置upload.html页面路由
    location = /upload.html {                                                        
            root /nginx;  # upload.html所在路径                                                       
    }

    location /upload {
            # 限制上传文件最大30MB
            upload_max_file_size 30m;
            # 设置后端处理交由@rename处理。由于nginx-upload-module模块在存储时并不是按上传的文件名存储的,所以需要自行改名。
            upload_pass @rename;
            # 指定上传文件存放目录,1表示按1位散列,将上传文件随机存到指定目录下的0、1、2、...、8、9目录中(这些目录要手动建立)
            upload_store /tmp/nginx 1;
            # 上传文件的访问权限,user:r表示用户只读,w表示可写
            upload_store_access user:r;

            # 设置传给后端处理的表单数据,包括上传的原始文件名,上传的内容类型,临时存储的路径
            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_pass_form_field "^submit$|^description$";

            # 设置上传文件的md5值和文件大小
            upload_aggregate_form_field "${upload_field_name}_md5" "$upload_file_md5";
            upload_aggregate_form_field "${upload_field_name}_size" "$upload_file_size";

            # 如果出现下列错误码则删除上传的文件
            upload_cleanup 400 404 499 500-505;
     }

    location @rename {
            # 后端处理
            proxy_pass http://localhost:81;
    }
}

上面的配置中,临时存储时是按1位散列来存储的,需要在上传目录下手动创建0~9几个目录。

 mkdir -p /tmp/nginx
 cd /tmp/nginx
 mkdir 1 2 3 4 5 6 7 8 9 0
 chown nginx:root . -R
2. 添加upload.html



上传



3. 添加后端处理服务 3.1 使用python来写后端服务

由于容器中并没有默认安装Python,要使用python作为后端服务,就需要先安装python及所需的库

apk add python3
pip3 install bottle
pip3 install shutilwhich

python源码:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

from bottle import *
import shutil

@post("/upload")
def postExample():
    try:
        dt = request.forms.dict
        filenames = dt.get('file.name')
        tmp_path = dt.get("file.tmp_path")
        filepaths = dt.get("file.path")
        count = filenames.__len__()
        dir = os.path.abspath(filepaths[0])
        for i in range(count):
            print("rename %s to %s" % (tmp_path[i],  os.path.join(dir, filenames[i])))
            target = os.path.join(dir, filenames[i])
            shutil.move(tmp_path[i], target)
            shutil.chown(target, "nginx", "root") # 由于shutil.move不会保持用户归属,所以需要显示修改,否则访问时会报403无访问权限
    except Exception as e:
        print("Exception:%s" % e)
        redirect("50x.html") # 如果是在容器中部署的nginx且映射了不同的端口,需要指定IP,端口
    redirect('/') # 如果是在容器中部署的nginx且映射了不同的端口,需要指定IP,端口

run(host='localhost', port=81)
3.2 使用go来写后端服务

如果不想在容器中额外安装东西,使用Go来作为后端服务是非常好的一个选择。只需要将源码编译成可执行文件,放到容器中运行即可。

go源码:

package main

import (
	"fmt"
	"net/http"
	"os/exec"
)

func main() {
	http.HandleFunc("/upload", func(w http.ResponseWriter, r *http.Request) {
		err := r.ParseMultipartForm(8192)
		if err != nil {
			http.Redirect(w, r, "50x.html", http.StatusMovedPermanently) // 如果是在容器中部署的nginx且映射了不同的端口,需要指定IP,端口
			return
		}
		filenames := r.Form.Get("file.name")
		tmp_path := r.Form.Get("file.tmp_path")
		filepaths := r.Form.Get("file.path")
		target := filepaths + "/" + filenames
		fmt.Printf("Rename:%s => %sn", tmp_path, target)
		cmd := exec.Command("mv", tmp_path, target) // 这里调用Linux系统的mv命令
		_, err = cmd.Output()
		if err != nil {
			fmt.Printf("Rename:%s => %s Failed:%sn", tmp_path, target, err.Error())
			http.Redirect(w, r, "50x.html", http.StatusMovedPermanently) // 如果是在容器中部署的nginx且映射了不同的端口,需要指定IP,端口
			return
		}
		http.Redirect(w, r, "/", http.StatusMovedPermanently) // 如果是在容器中部署的nginx且映射了不同的端口,需要指定IP,端口
	})
	fmt.Printf("Listen at 81n")
	http.ListenAndServe("localhost:81", nil)
}

如果不想在Linux中安装Go环境,也可以直接在Windows下编译成Linux可执行文件,在Windows控制台输入下面的命令:

set GOOS=linux

再编译上面的文件生成Linux下的可执行文件,然后复制到容器中,添加上执行权限,再运行。

四、获取上传进度 1.修改配置
# 开辟一个空间proxied来存储跟踪上传的信息1MB
upload_progress proxied 1m;
server {
    ……
    location ^~ /progress {
        # 报告上传的信息
        report_uploads proxied;
    }
    location /upload {
        ...
        # 上传完成后,仍然保存上传信息5s
        track_uploads proxied 5s;
    }
}
2. 修改上传页面upload.html
 
(progress)

五、添加验证 1. 生成验证文件
htpasswd -c .httppasswd test

这里test是账号,密码在执行命令过程中会要求输入两次密码。

htpasswd命令需要httpd-tools包,如果没有可以使用下面的命令进行安装

apt install httpd-tools # ubuntu
yum install httpd-tools # centos

将生成的.httppasswd文件复制到容器路径 /etc/nginx/conf.d/.httppasswd,当然也可以指定其它路径,但要求配置中的路径与之一致。

也可以直接在指定路径创建一个空文件,将.httppasswd文件的内容复制过去。

2.修改配置
server {
	……
	location / {
  		……
        auth_basic "download";
        auth_basic_user_file /etc/nginx/conf.d/.httppasswd;
    }
}    

使用nginx -s reload让配置生效。此时访问页面就会弹出一个登录对话框,要求输入账号与密码


附上配置文件/etc/nginx/conf.d/default.conf内容:

# 开辟一个空间proxied来存储跟踪上传的信息1MB
upload_progress proxied 1m;
server {
    listen       80;
    server_name  localhost;
    client_max_body_size 500m;
    charset utf-8; # 设置字符编码,避免中文乱码
    upload_limit_rate 1M; # 限制上传速度最大1M

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   /nginx/share; # 根目录
		autoindex   on; # 开启索引功能
		autoindex_exact_size off; # 关闭计算文件确切大小(单位bytes),只显示大概大小(单位kb、mb、gb)
		autoindex_localtime on; # 显示本地时间
		auth_basic "download"; # 身份验证
		auth_basic_user_file /etc/nginx/conf.d/.httppasswd; # 身份验证文件
    }
   
    # 设置upload.html页面路由
    location = /upload.html {
		root /nginx;
    }

    location /upload {
        # 指定上传文件存放目录,1表示按1位散列,将上传文件随机存到指定目录下的0、1、2、...、8、9目录中(这些目录要手动建立)
        upload_store /tmp/nginx 1;
         # 上传文件的访问权限,user:r表示用户只读,w表示可写
        upload_store_access user:rw;

		# 设置传给后端处理的表单数据,包括上传的原始文件名,上传的内容类型,临时存储的路径
        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.tmp_path "$upload_tmp_path";
		upload_set_form_field $upload_field_name.path "/nginx/share";
        upload_pass_form_field "^submit$|^description$";
        # 设置后端处理交由@rename处理。由于nginx-upload-module模块在存储时并不是按上传的文件名存储的,所以需要自行改名。
		upload_pass @rename;

		# 设置上传文件的md5值和文件大小
        upload_aggregate_form_field "${upload_field_name}_md5" "$upload_file_md5";
        upload_aggregate_form_field "${upload_field_name}_size" "$upload_file_size";

        # 如果出现下列错误码则删除上传的文件
        upload_cleanup 400 404 499 500-505;
		
		# 上传完成后,仍然保存上传信息5s
		track_uploads proxied 5s;
    }

    location @rename {
        #后端处理
		proxy_pass http://localhost:81;
    }

    # 开辟一个空间proxied来存储跟踪上传的信息1MB
    location ^~ /progress {
        # 报告上传的信息
        report_uploads proxied;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ .php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ .php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /.ht {
    #    deny  all;
    #}
}

参考:
https://breeze2.github.io/blog/scheme-nginx-php-js-upload-process
https://www.tiantanhao.com/34031.html
https://blog.csdn.net/scugxl/article/details/107180138
https://octocat9lee.github.io/2020/03/11/Nginx%E6%90%AD%E5%BB%BA%E6%96%87%E4%BB%B6%E6%9C%8D%E5%8A%A1%E5%99%A8/

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/882340.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号