在容器中使用nginx搭建上传下载服务器


Posted in Servers onMay 11, 2022

一、安装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

在容器中使用nginx搭建上传下载服务器

三、支持文件上传

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>上传</title>
</head>
<body>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<form name="upload" method="POST" enctype="multipart/form-data" action="upload">
<input type="file" name="file"/>
<input type="submit" name="submit" value="上传"/>
</form>
</body>
</html>

3. 添加后面的处理服务

需要先安装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)

四、获取上传进度

1.修改配置

# 开辟一个空间proxied来存储跟踪上传的信息1MB
upload_progress proxied 1m;
server {
    ……
    location ^~ /progress {
        # 报告上传的信息
        report_uploads proxied;
    }
    location /upload {
        ...
        # 上传完成后,仍然保存上传信息5s
        track_uploads proxied 5s;
    }
}

2. 修改上传页面

<form id="upload" enctype="multipart/form-data" action="/upload" method="post" onsubmit="openProgressBar(); return true;">
    <input name="file" type="file" label="fileupload" />
    <input type="submit" value="Upload File" />
</form>
<div>
    <div id="progress" style="width: 400px; border: 1px solid black">
        <div id="progressbar" style="width: 1px; background-color: black; border: 1px solid white"> </div>
    </div>
   <div id="tp">(progress)</div>
</div>
<script type="text/javascript">
    var interval = null;
    var uuid = "";
    function openProgressBar() {
        for (var i = 0; i < 32; i++) {
            uuid += Math.floor(Math.random() * 16).toString(16);
        }
        document.getElementById("upload").action = "/upload?X-Progress-ID=" + uuid;
        /* 每隔一秒查询一下上传进度 */
        interval = window.setInterval(function () {
            fetch(uuid);
        }, 1000);
    }
    function fetch(uuid) {
        var req = new XMLHttpRequest();
        req.open("GET", "/progress", 1);
        req.setRequestHeader("X-Progress-ID", uuid);
        req.onreadystatechange = function () {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    var upload = eval(req.responseText);
                    document.getElementById('tp').innerHTML = upload.state;
                    /* 更新进度条 */
                    if (upload.state == 'done' || upload.state == 'uploading') {
                        var bar = document.getElementById('progressbar');
                        var w = 400 * upload.received / upload.size;
                        bar.style.width = w + 'px';
                    }
                    /* 上传完成,不再查询进度 */
                    if (upload.state == 'done') {
                        window.clearTimeout(interval);
                    }
                    if (upload.state == 'error') {
                        window.clearTimeout(interval);
                        alert('something wrong');
                    }
                }
            }
        }
        req.send(null);
    }
</script>

在容器中使用nginx搭建上传下载服务器

参考:

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/

到此这篇关于容器中使用ngnix搭建支持上传下载的文件服务器的文章就介绍到这了!


Tags in this post...

Servers 相关文章推荐
Nginx反向代理多个服务器的实现方法
Mar 31 Servers
nginx优化的六点方法
Mar 31 Servers
Nginx中break与last的区别详析
Mar 31 Servers
Nginx搭建rtmp直播服务器实现代码
Mar 31 Servers
详解nginx进程锁的实现
Jun 14 Servers
解决使用了nginx获取IP地址都是127.0.0.1 的问题
Sep 25 Servers
教你利用Nginx 服务搭建子域环境提升二维地图加载性能的步骤
Sep 25 Servers
Nginx配置https的实现
Nov 27 Servers
教你快速构建一个基于nginx的web集群项目
Nov 27 Servers
Windows Server 2012 修改远程默认端口3389的方法
Apr 28 Servers
如何开启Apache,Nginx和IIS服务器的GZIP压缩功能
Apr 29 Servers
阿里云国际版 使用Nginx作为HTTPS转发代理服务器
May 11 #Servers
nginx 配置缓存
May 11 #Servers
Nginx的gzip相关介绍
May 11 #Servers
详解如何使用Nginx解决跨域问题
May 06 #Servers
配置nginx负载均衡
May 06 #Servers
tomcat下部署jenkins的方法
排查Tomcat进程假死的问题
May 06 #Servers
You might like
解析PHP正则提取或替换img标记属性
2013/06/26 PHP
php中ob函数缓冲机制深入理解
2015/08/03 PHP
lnmp安装多版本PHP共存的方法详解
2018/08/02 PHP
laravel 获取当前url的别名方法
2019/10/11 PHP
利用JQuery动画制作滑动菜单项效果实现步骤及代码
2013/02/07 Javascript
JavaScript中的常见问题解决方法(乱码,IE缓存,代理)
2013/11/28 Javascript
AngularJS iframe跨域打开内容时报错误的解决办法
2015/01/26 Javascript
JavaScript保存并运算页面中数字类型变量的写法
2015/07/06 Javascript
jQuery使用$.ajax进行异步刷新的方法(附demo下载)
2015/12/04 Javascript
js密码强度检测
2016/01/07 Javascript
JSON字符串转换JSONObject和JSONArray的方法
2016/06/03 Javascript
完美JQuery图片切换效果的简单实现
2016/07/21 Javascript
H5用户注册表单页 注册模态框!
2016/09/17 Javascript
js数组方法reduce经典用法代码分享
2018/01/07 Javascript
深入了解javascript 数组的sort方法
2018/06/01 Javascript
JS获取月的第几周和年的第几周实例代码
2018/12/05 Javascript
小程序外卖订单界面的示例代码
2019/12/30 Javascript
JS实现横向跑马灯效果代码
2020/04/20 Javascript
深入分析JavaScript 事件循环(Event Loop)
2020/06/19 Javascript
python使用BeautifulSoup分析网页信息的方法
2015/04/04 Python
Python使用defaultdict读取文件各列的方法
2017/05/11 Python
django如何连接已存在数据的数据库
2018/08/14 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
使用python实现哈希表、字典、集合操作
2019/12/22 Python
使用OpenCV实现道路车辆计数的使用方法
2020/07/15 Python
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
美国伊甸园兄弟种子公司:Eden Brothers
2018/07/01 全球购物
大学毕业感言
2014/01/10 职场文书
精彩自我鉴定
2014/01/16 职场文书
违纪学生保证书
2015/02/27 职场文书
2015年食品安全工作总结
2015/05/15 职场文书
2016年安全生产先进个人事迹材料
2016/02/29 职场文书
Go 自定义package包设置与导入操作
2021/05/06 Golang
Html5获取用户当前位置的几种方式
2022/01/18 HTML / CSS
vue @ ~ 相对路径 路径别名设置方式
2022/06/05 Vue.js