这就是我最终得到的结果。感谢Scott S,他向我暗示了解决方案。
阿帕奇配置:
ServerName listing.example.com
# A path to a location which you wanted listed
DocumentRoot "/path/to/listed/location"
<Directory "/path/to/listed/location">
# Ignore .htaccess files
AllowOverride None
# Disable Apache's own indexing, CGI execution and Apache Includes
Options -Indexes -MultiViews -ExecCGI -Includes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
<Directory "/path/to/php/listing/app">
Options -MultiViews ExecCGI
Order allow,deny
Allow from all
</Directory>
<IfModule dir_module>
# index.php should not be listed here as we will not want PHP scripts to be executed
DirectoryIndex index.html index.htm
</IfModule>
<IfModule alias_module>
# This is for CSS/JS files
Alias /~media /path/to/php/listing/app/media
</IfModule>
<IfModule xsendfile_module>
# Because the files listed might be large, we want to pass the file handling
# to Apache via XSendFile Module
# @see: https://tn123.org/mod_xsendfile/
XSendFile on
XSendFilePath "/path/to/listed/location"
</IfModule>
# Uncomment the two setting below if your listing a mounted drive
# EnableSendfile Off
# EnableMMAP Off
<IfModule rewrite_module>
RewriteEngine On
# Make sure there are trailing slashes for Directory URLs
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^(.*[^/])$ $1/ [R=302,L]
# Pass all file+dir requests to a PHP handler
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
RewriteRule .* /path/to/php/listing/app/index.php/$0 [L]
</IfModule>
和(一个非常简化的版本)我的 php 脚本:
<?php
if (my_authentication_check()) {
$requested_path = realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI']);
$filename = substr($requested_path, strrpos($requested_path, DIRECTORY_SEPARATOR) + 1);
if ($requested_path) {
if (is_dir($requested_path)) {
// Show dir contents
$dir_contents = scandir($requested_path);
} else {
// Pass file download to XSendFile module
header('X-Sendfile: ' . $requested_path);
header('Content-Type: ' . my_get_file_mime($filename));
exit;
}
} else {
// display 404 error
}
} else {
// redirect to login screen, or display an error... whatever you fancy
}
实际上,我使用 Kohana 框架和我自己的库来处理身份验证检查、显示列表等。您还必须考虑文件权限。例如,在 *nix 系统上,您需要检查 dirs 的可执行权限,而在 Windows 上,读取权限就足够了。