在容器中使用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配置SSL证书出错解决方案
Mar 31 Servers
nginx简单配置多个server的方法
Mar 31 Servers
Nginx域名转发https访问的实现
Mar 31 Servers
如何在centos上使用yum安装rabbitmq-server
Mar 31 Servers
Nginx如何配置Http、Https、WS、WSS的方法步骤
May 11 Servers
Nginx location 和 proxy_pass路径配置问题小结
Sep 04 Servers
Nginx 路由转发和反向代理location配置实现
Nov 11 Servers
Nginx虚拟主机的配置步骤过程全解
Mar 31 Servers
使用 DataAnt 监控 Apache APISIX的原理解析
Jul 07 Servers
apache虚拟主机配置的三种方式(小结)
Jul 23 Servers
Nginx 502 bad gateway错误解决的九种方案及原因
Aug 14 Servers
修改Nginx配置返回指定content-type的方法
Sep 23 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在数组中查找指定值的方法
2015/03/17 PHP
Docker 如何布置PHP开发环境
2016/06/21 PHP
php利用imagemagick实现复古老照片效果实例
2017/02/16 PHP
PHP实现防盗链的方法分析
2017/07/25 PHP
yii2.0框架实现上传excel文件后导入到数据库的方法示例
2020/04/13 PHP
Ctrl+Enter提交内容信息
2006/06/26 Javascript
javascript 跨浏览器开发经验总结(五) js 事件
2010/05/19 Javascript
把jQuery的类、插件封装成seajs的模块的方法
2014/03/12 Javascript
理解js回收机制通俗易懂版
2016/02/29 Javascript
js实现淡入淡出轮播切换功能
2017/01/13 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
ES6新特性之模块Module用法详解
2017/04/01 Javascript
使用jquery DataTable和ajax向页面显示数据列表的方法
2018/08/09 jQuery
当vue路由变化时,改变导航栏的样式方法
2018/08/22 Javascript
详解vue 兼容IE报错解决方案
2018/12/29 Javascript
JavaScrip数组去重操作实例小结
2019/06/20 Javascript
判断网页编码的方法python版
2016/08/12 Python
python通过opencv实现批量剪切图片
2017/11/13 Python
python实现键盘控制鼠标移动
2020/11/27 Python
python实现学员管理系统
2019/02/26 Python
使用tqdm显示Python代码执行进度功能
2019/12/08 Python
flask框架自定义url转换器操作详解
2020/01/25 Python
使用 Python 遍历目录树的方法
2020/02/29 Python
在pycharm中文件取消用 pytest模式打开的操作
2020/09/01 Python
Parfume Klik丹麦:香水网上商店
2018/07/10 全球购物
PatPat德国:妈妈的每日优惠
2019/10/02 全球购物
索桥的故事教学反思
2014/02/06 职场文书
学生会部长竞聘书
2014/03/31 职场文书
竞选副班长演讲稿
2014/04/24 职场文书
小学生关于梦想的演讲稿
2014/08/22 职场文书
社区班子个人对照检查材料思想汇报
2014/10/07 职场文书
骨干教师事迹材料
2014/12/17 职场文书
离职感谢信
2015/01/21 职场文书
高中诗歌鉴赏教学反思
2016/02/16 职场文书
小程序后台PHP版本部署运行 LNMP+WNMP
2021/04/01 Servers
Python内置类型集合set和frozenset的使用详解
2022/04/26 Python