需在Nginx日志中启用$body_bytes_sent、$status等字段,结合状态码(200/206)、响应体大小(>1MB)、文件后缀及请求类型过滤真实下载,再按总传输字节或请求数排序统计热门资源。

要通过 Nginx 访问日志统计文件下载行为并排出热门下载资源,关键在于识别“下载类请求”、准确提取文件路径,并按实际传输字节数(而非请求数)或请求频次排序。核心不是简单数 URL 出现次数,而是结合状态码、响应大小、路径特征和用户行为综合判断。
确认日志格式是否支持精准识别
Nginx 默认日志可能不包含足够字段。必须确保 log_format 中启用以下字段:
- $body_bytes_sent:纯响应体大小(不含响应头),用于衡量真实带宽消耗;
- $status:过滤出 200、206(分段下载)等成功响应;
-
$request 或正则提取的路径(如
"GET /files/report.pdf HTTP/1.1"); - $http_user_agent 和 $http_referer:辅助判断是否为人工下载、爬虫或盗链。
示例推荐配置:
log_format download '$remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';识别真正的下载请求
不能仅靠 URL 含 “download” 就判定为下载——很多是后台接口。更可靠的依据是:
- 响应体大:$body_bytes_sent > 1MB(如 PDF、ZIP、MP4、安装包);
- 常见下载后缀:.pdf、.zip、.exe、.dmg、.tar.gz、.apk、.mp4、.iso;
-
HTTP 状态码合理:优先统计
$status == 200 || $status == 206; - 排除干扰:跳过 301/302 重定向、4xx/5xx 错误、HEAD 请求、空响应($body_bytes_sent == 0)。
命令行快速统计热门下载资源(Top 10)
以下命令自动提取路径、过滤有效下载、按总传输字节降序排列:
awk '$9 ~ /^(200|206)$/ && $10 > 1024000 { match($0, /"[A-Z]+[[:space:]]+([^[:space:]]+)[[:space:]]+HTTP\//, m); if (m[1]) print $10, m[1] }' /var/log/nginx/access.log | sort -nr | head -10说明:
-
$9是状态码字段(通常第 9 列),$10是$body_bytes_sent(需确认你的日志中该值所在列); -
match(...)安全提取请求路径,避免因引号或空格错位导致字段偏移; - 结果第一列为总传输字节,第二列为文件路径,一目了然看出哪个资源吃带宽最多。
补充分析提升判断准确性
单看字节数可能失真(例如一个大文件被 1 人下载 10 次 vs 10 人各下 1 次)。建议交叉验证:
- 按请求数排行:统计相同路径出现次数,找高频小文件(如 favicon.ico、common.js 被反复拉取,可能是前端异常);
-
查 Referer 为空或异常域名:
awk '$9==200 && $10>500000 && $12 ~ /^"(-|https?:\/\/(?!yourdomain\.com).*)"$/{print $1, $12, $7}' access.log—— 可发现盗链; -
看 User-Agent:大量
curl/、wget/、python-requests行为,大概率是非人工批量下载,需评估是否合规。











