
在许多应用场景中,文件通常通过直接链接供用户下载,例如 https://exampledomain.com/files/file.pdf。然而,当我们需要对这些下载行为进行统计、日志记录或执行其他预处理逻辑时,直接的文件访问会绕过服务器端的 PHP 脚本,导致无法捕获相关信息。例如,使用像 iNamik/PHP-Download-Tracker 这样的下载追踪脚本时,如果用户通过 index.php(或 download.php)点击文件进行下载,脚本可以正常记录;但如果用户直接访问 /files/file.pdf,则追踪脚本会被绕过,日志功能失效。
我们的目标是,即使是直接访问文件链接,也能让请求自动重写到 PHP 追踪脚本,例如将 https://exampledomain.com/files/file.pdf 内部重写为 https://exampledomain.com/files/download.php?file=file.pdf,从而确保每次下载都能被追踪和记录。
Apache 的 mod_rewrite 模块提供了强大的 URL 重写功能,可以通过 .htaccess 文件在目录级别进行配置。我们将利用这一特性来实现下载链接的自动重写。
在开始配置之前,请确保以下条件已满足:
Apache 服务器已安装并运行。
mod_rewrite 模块已启用。 通常在 Apache 配置文件中通过 a2enmod rewrite 命令(Debian/Ubuntu)或取消注释 LoadModule rewrite_module modules/mod_rewrite.so 来启用。
目标目录允许 .htaccess 文件覆盖。 在 Apache 站点的配置文件(例如 httpd.conf 或虚拟主机配置)中,确保下载文件所在的目录(例如 /var/www/html/files/)的 Directory 配置中包含 AllowOverride All。
<Directory /var/www/html/files/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>PHP 下载追踪脚本已就绪。 假设您的追踪脚本名为 download.php,并位于下载文件所在的目录(例如 /files/)。此脚本应能接收 file 参数,处理下载,并进行日志记录。
在您的文件下载目录(例如 public_html/files/)中创建一个名为 .htaccess 的文件,并添加以下内容:
RewriteEngine On RewriteBase /files/ RewriteRule ^(.+(file|FILE))$ download.php?file=$1 [L]
RewriteEngine On: 这一指令用于开启 mod_rewrite 重写引擎。它是使用任何重写规则的前提。
RewriteBase /files/: 这一指令设置了重写规则的基础 URL 路径。如果您的 .htaccess 文件位于 https://exampledomain.com/files/ 对应的服务器文件系统路径下,那么 RewriteBase /files/ 告诉 Apache,后续的 RewriteRule 匹配的是 /files/ 之后的路径部分。例如,当访问 https://exampledomain.com/files/file.pdf 时,RewriteRule 将会针对 file.pdf 进行匹配。
RewriteRule ^(.+(file|FILE))$ download.php?file= [L]: 这是核心的重写规则。
^(.+(file|FILE))$: 这是一个正则表达式。
通用化重写规则建议: 为了更通用地匹配所有文件(除了 download.php 自身),并将其重写到 download.php 脚本,我们建议使用更灵活的正则表达式。如果您希望匹配任何带有扩展名的文件,可以考虑使用以下规则:
RewriteRule ^([^/]+\.[a-zA-Z0-9]+)$ download.php?file=$1 [L]
此规则会匹配 files/ 目录下所有包含扩展名的文件(如 file.pdf, document.docx, archive.zip 等),并将其文件名作为 file 参数传递给 download.php。
或者,如果您希望捕获所有非 download.php 的请求并将其视为文件下载:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?!download\.php)(.+)$ download.php?file=$1 [L,QSA]这个更高级的规则:
在大多数情况下,如果 download.php 位于 RewriteBase 目录下,并且您想追踪所有其他文件的直接访问,最简单且有效的规则是:
RewriteRule ^(?!download\.php)(.+)$ download.php?file=$1 [L]
这个规则会捕获所有不以 download.php 开头的请求路径,并将其作为 $1 传递给 download.php。
download.php?file=$1: 这是重写的目标 URL。$1 是正则表达式中第一个捕获组匹配到的内容,即文件名。这样,当用户访问 file.pdf 时,服务器内部会将其处理为对 download.php?file=file.pdf 的请求。
[L]: Last 标志。这个标志告诉 mod_rewrite,如果当前规则匹配成功,则停止处理后续的重写规则。这对于避免不必要的循环或冲突非常重要。
考虑到实际应用中对各种文件类型的追踪需求,以下是一个更通用且推荐的 .htaccess 配置:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /files/
# 排除 download.php 自身,避免无限重写循环
# 匹配所有非 download.php 的请求,并将其作为文件参数传递
RewriteRule ^(?!download\.php)(.+)$ download.php?file=$1 [L]
</IfModule>通过在文件下载目录中配置 .htaccess 文件,并利用 Apache mod_rewrite 模块,我们可以有效地将所有直接文件下载链接重写到 PHP 下载追踪脚本。这不仅解决了直接下载绕过日志系统的问题,还为收集下载统计数据、实现权限控制或其他自定义逻辑提供了基础。选择合适的正则表达式是实现这一目标的关键,建议使用更通用的规则来覆盖所有预期的文件下载场景。
以上就是使用 Apache .htaccess 重写规则实现直接下载链接的追踪与日志记录的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号