XSendFile与mod_rewrite(相对路径)共存异常求助
当请求通过mod_rewrite重写后,Apache的内部请求上下文被修改,XSendFile在解析相对路径时,错误地将其关联到原始请求的URL路径(而非PHP脚本所在的文件系统目录),因此出现redirect:/xsendfile_test/target_file.mp4这类错误路径——它把相对路径当成了URL重定向路径,而非文件系统路径。
未重写的请求直接访问PHP脚本时,XSendFile能正确基于脚本所在的文件系统目录解析相对路径,所以正常工作。
下面提供几种无需修改全局Apache配置的方案:
方案1:动态生成文件绝对路径(推荐)
在PHP脚本中,用__DIR__常量(表示当前脚本所在的目录)动态构造文件的绝对路径,不需要硬编码服务器路径:
<?php $video = __DIR__ . '/target_file.mp4'; header('X-Sendfile: ' . $video); exit(); ?>
这种方式既避免了硬编码绝对路径,又能让XSendFile直接拿到正确的文件系统路径,不受URL重写影响。
方案2:给RewriteRule添加PT标志
修改.htaccess中的Rewrite规则,加上PT(Pass Through)标志,让重写后的请求路径继续被后续模块(包括XSendFile)正确处理:
RewriteEngine On XSendFile On RewriteRule ^file.mp4$ file.php [QSA,L,PT]
PT标志会告诉mod_rewrite,把重写后的路径当作文件系统路径传递给后续处理模块,而不是保留原始URL的上下文,这样XSendFile就能正确解析相对路径了。
方案3:在.htaccess中设置XSendFilePath(备选)
如果服务器允许在.htaccess中覆盖XSendFilePath配置,可以添加当前目录的绝对路径到白名单:
RewriteEngine On XSendFile On XSendFilePath /var/www/xsendfile_test/ RewriteRule ^file.mp4$ file.php [QSA,L]
不过这种方式需要硬编码目录路径,可能不符合你不想依赖服务器配置的需求,但如果部署环境允许,也是一种可行方案。
XSendFile对相对路径的解析逻辑确实会受请求上下文(比如重写、CGI模式)影响,这也是官方文档提到相对路径可能导致意外结果的原因。动态生成绝对路径的方案兼容性最好,同时不需要修改服务器配置,是最稳妥的选择。
内容的提问来源于stack exchange,提问作者AdamM

