upload-progress: NGINX 上传进度跟踪模块
安装
您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:
- RedHat Enterprise Linux 7、8、9 和 10
- CentOS 7、8、9
- AlmaLinux 8、9
- Rocky Linux 8、9
- Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-upload-progress
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-upload-progress
通过在 /etc/nginx/nginx.conf 顶部添加以下内容来启用模块:
load_module modules/ngx_http_uploadprogress_module.so;
本文档描述了 nginx-module-upload-progress v0.9.4,于 2025 年 3 月 15 日发布。
介绍
nginx_uploadprogress_module 是一个上传进度系统的实现,它监控 RFC1867 POST 上传在传输到上游服务器时的进度。
它通过跟踪 Nginx 代理到上游服务器的上传,而不分析上传的内容,并提供一个 Web API,以 JavaScript、Json 或任何其他格式报告上传进度(通过模板的帮助)。
它之所以有效,是因为 Nginx 作为上游服务器的加速器,在将上传的 POST 内容传输到上游服务器之前将其存储在磁盘上。每个单独的 POST 上传请求应包含一个唯一的进度标识符。
该模块的版权归 (c) 2007-2012 Brice Figureau 所有,并根据 BSD 许可证授权(见 LICENSE)。 * rbtree 和 shm_zone 代码基于 Igor Sysoev 的 limit_zone Nginx 模块。 * expire header 代码基于 Igor Sysoev 的 header_filter Nginx 模块。
JSON 的想法和机制的想法基于 Lighttpd mod_uploadprogress: http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back
警告: * 当使用 --with-debug 编译时,此模块将生成大量日志消息。
不兼容的更改
v0.9.0:
JSONP 现在是进度探测的默认输出。如果您依赖此模块提供已弃用的 Java 输出,请使用: upload_progress_java_output 在进度探测位置中。
配置
每个上传请求应分配一个唯一标识符。此唯一标识符将用于存储请求并引用以进行报告。 该标识符可以作为 GET 参数或名为 X-Progress-ID 的 HTTP 头传输。
upload_progress
+++++++++++++++
:语法: upload_progress
track_uploads
+++++++++++++
:语法: track_uploads
report_uploads
++++++++++++++
:语法: report_uploads
* 上传请求已结束:
new Object({ 'state' : 'done' })
* 上传请求生成了 HTTP 错误
new Object({ 'state' : 'error', 'status' : <error code> })
一个可以用于跟踪客户端的错误代码是 413(请求实体过大)。
* 上传请求正在进行中:
new Object({ 'state' : 'uploading', 'received' : <size_received>, 'size' : <total_size>})
可以返回纯 JSON 而不是此 JavaScript(请参见 upload_progress_json_output)。
还可以使用指令完全配置响应格式:
upload_progress_template
对此位置的 HTTP 请求必须具有 X-Progress-ID 参数或 HTTP 头,包含有效的正在进行的上传的唯一标识符。
upload_progress_content_type
++++++++++++++++++++++++++++
:语法: upload_progress_content_type
upload_progress_header
++++++++++++++++++++++
:语法: upload_progress_header
upload_progress_jsonp_parameter
++++++++++++++++++++++
:语法: upload_progress_jsonp_parameter
upload_progress_java_output +++++++++++++++++++++++++++ :语法: upload_progress_java_output :默认值: 不适用 :上下文: location :描述: 此指令将所有内容设置为输出为 eval() 兼容的 JavaScript 代码。
upload_progress_json_output +++++++++++++++++++++++++++ :语法: upload_progress_json_output :默认值: 不适用 :上下文: location :描述: 此指令将所有内容设置为输出为纯 JSON。
upload_progress_jsonp_output ++++++++++++++++++++++++++++ :语法: upload_progress_jsonp_output :默认值: 不适用 :上下文: location :描述: 此指令将所有内容设置为输出为 jsonp(类似于 JSON 输出,但带有回调)。
upload_progress_template
++++++++++++++++++++++++
:语法: upload_progress_template
Nginx 将用上传的相应值替换以下变量的值:
* $uploadprogress_length: 上传的总大小
* $uploadprogress_received: 服务器迄今为止接收到的内容
* $uploadprogress_status: HTTP 错误时的错误代码
* $uploadprogress_callback: 如果提供为名为 'callback' 的 GET 查询参数,则为 jsonp 回调名称
例如,要返回 XML(而不是默认的 JavaScript 或 JSON):
upload_progress_content_type 'text/xml';
upload_progress_template starting '<upload><state>starting</state></upload>';
upload_progress_template uploading '<upload><state>uploading</state><size>$uploadprogress_length</size><uploaded>$uploadprogress_received</uploaded></upload>';
upload_progress_template done '<upload><state>done</state></upload>';
upload_progress_template error '<upload><state>error</state><code>$uploadprogress_status</code></upload>';
JSONP 响应示例:
upload_progress_template starting "$uploadprogress_callback({ \"state\" : \"starting\"});";
upload_progress_template error "$uploadprogress_callback({ \"state\" : \"error\", \"status\" : $uploadprogress_status });";
upload_progress_template done "$uploadprogress_callback({ \"state\" : \"done\"});";
upload_progress_template uploading "$uploadprogress_callback({ \"state\" : \"uploading\", \"received\" : $uploadprogress_received, \"size\" : $uploadprogress_length });";
配置示例: +++++++++++++++++++++
http {
# 在名为 'proxied' 的区域下保留 1MB 以跟踪上传
upload_progress proxied 1m;
server { listen 127.0.0.1 default; server_name _ *;
root /path/to/root;
location / {
# 代理到上游服务器
proxy_pass http://127.0.0.1;
proxy_redirect default;
# 在 'proxied' 区域跟踪上传
# 在完成后记住连接 30 秒
track_uploads proxied 30s;
}
location ^~ /progress {
# 报告在 'proxied' 区域跟踪的上传
report_uploads proxied;
}
}
使用示例
(基于 Lighttd mod_uploadprogress 模块示例):
首先,我们需要一个上传表单:
以及一个进度条来可视化进度:
然后,我们需要生成唯一标识符并在提交操作时启动上传。这也将启动 AJAX 进度报告机制。
interval = null;
function openProgressBar() { / 生成随机的 progress-id / uuid = ""; for (i = 0; i < 32; i++) { uuid += Math.floor(Math.random() * 16).toString(16); } / 修补表单动作标签以包含 progress-id / document.getElementById("upload").action="/upload.php?X-Progress-ID=" + uuid;
/ 每 1000 毫秒调用进度更新器 / interval = window.setInterval( function () { fetch(uuid); }, 1000 ); }
function fetch(uuid) { 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) { / 简单的 JSON 解析器 / var upload = eval(req.responseText);
document.getElementById('tp').innerHTML = upload.state;
/* 改变内部进度条的宽度 */
if (upload.state == 'done' || upload.state == 'uploading') {
bar = document.getElementById('progressbar');
w = 400 * upload.received / upload.size;
bar.style.width = w + 'px';
}
/* 我们完成了,停止间隔 */
if (upload.state == 'done') {
window.clearTimeout(interval);
}
} } } req.send(null); }
伴随软件
此软件还可以与 Valery Kholodkov 的 Nginx 上传模块一起使用: http://www.grid.net.ru/nginx/upload.en.html
您还可以在客户端使用以下 JavaScript 库: http://drogomir.com/blog/2008/6/30/upload-progress-script-with-safari-support
请注意,当使用 jQuery AJAX 进行进度监控时,例如: https://github.com/drogus/jquery-upload-progress 您应确保设置 upload_progress 模板参数: upload_progress_json_output 或 upload_progress_jsonp_output 具体取决于您的 jQuery AJAX dataType 设置。
GitHub
您可以在 nginx-module-upload-progress 的 GitHub 仓库中找到有关此模块的其他配置提示和文档。