在容器中使用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启动失败的几种错误处理
Apr 01 Servers
nginx服务器的下载安装与使用详解
Aug 02 Servers
Docker 镜像介绍以及commit相关操作
Apr 13 Servers
nginx 添加http_stub_status_module模块
May 25 Servers
Linux磁盘管理方法介绍
Jun 01 Servers
win sever 2022如何占用操作主机角色
Jun 25 Servers
git中cherry-pick命令的使用教程
Jun 25 Servers
设置IIS Express并发数
Jul 07 Servers
在windows server 2012 r2中安装mysql的详细步骤
Jul 23 Servers
nginx配置指令之server_name的具体使用
Aug 14 Servers
ubuntu端向日葵键盘输入卡顿问题及解决
Dec 24 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
joomla jce editor 解决上传中文名文件失败问题
2013/06/09 PHP
PHP内置加密函数详解
2016/11/20 PHP
PHP中检索字符串的方法分析【strstr与substr_count方法】
2017/02/17 PHP
PHP simplexml_load_string()函数实例讲解
2019/02/03 PHP
javascript Zifa FormValid 0.1表单验证 代码打包下载
2007/06/08 Javascript
深入理解JavaScript系列(12) 变量对象(Variable Object)
2012/01/16 Javascript
页面回到顶部的三种实现(锚标记,js)
2012/10/01 Javascript
使用JQUERY进行后台页面布局控制DIV实现左右式
2014/01/07 Javascript
JavaScript 实现鼠标拖动元素实例代码
2014/02/24 Javascript
全面兼容的javascript时间格式化函数(比较实用)
2014/05/14 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
2015/03/18 Javascript
JavaScript中的函数(二)
2015/12/23 Javascript
jQuery form 表单验证插件(fieldValue)校验表单
2016/01/24 Javascript
JS触发服务器控件的单击事件(详解)
2016/08/06 Javascript
Vue.js每天必学之内部响应式原理探究
2016/09/07 Javascript
JavaScript基于DOM操作实现简单的数学运算功能示例
2017/01/16 Javascript
jQuery菜单实例(全选,反选,取消)
2017/08/28 jQuery
Angular设置别名alias的方法
2018/11/08 Javascript
微信小程序实现购物页面左右联动
2019/02/15 Javascript
nuxt.js 在middleware(中间件)中实现路由鉴权操作
2020/11/06 Javascript
[01:23]一分钟告诉你 DOTA2为什么叫信仰2
2014/06/20 DOTA
Python实现八皇后问题示例代码
2018/12/09 Python
Django Rest framework权限的详细用法
2019/07/25 Python
Python 获取numpy.array索引值的实例
2019/12/06 Python
Python3中的f-Strings增强版字符串格式化方法
2020/03/04 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
2020/06/23 Python
纯CSS3编写的的精美动画进度条(无flash/无图像/无脚本/附源码)
2013/01/07 HTML / CSS
检测浏览器对HTML5和CSS3支持度的方法
2015/06/25 HTML / CSS
意大利制造的西装、衬衫和针对男士量身定制的服装:Lanieri
2018/04/08 全球购物
行政经理的岗位职责
2013/11/23 职场文书
人民调解员先进事迹材料
2014/05/08 职场文书
消防标语大全
2014/06/07 职场文书
整改落实自查报告
2014/11/05 职场文书
旷课检讨书范文
2015/01/27 职场文书
2016干部作风整顿心得体会
2016/01/22 职场文书
Golang入门之计时器
2022/05/04 Golang