PHP显示/下载webserver根目录之外的目录文件

时间:2010-12-07 22:17:37

标签: php html directory

我已下载并将这个非常简单的文件浏览器系统(称为Indexer)添加到我的XAMPP服务器中。

我的XAMMP服务器在我的C:驱动器上,但我希望Indexer在我的G:驱动器上显示一个目录。但是当我改变(我认为是)正确的配置变量时,它就无法正常工作。

以下是我认为与该问题有关的代码:

// configuration  
$Root = realpath("G:/test");  
$AllowDownload = TRUE;  
$WebServerPath = dirname("G:/test");

以及稍后的代码......

elseif ($AllowDownload) {  

        echo "<a href=\"http://".getenv("SERVER_NAME").$WebServerPath."/$rel_path".$item["filename"]."\">".$item["name"]."</a>";
    }

这是发生的事情:脚本 正确显示G:驱动器上“test”目录的内容,但是当我单击文件名,下载/查看文件时,链接是因为php构造错误的链接(我猜)。 链接如下所示:http:// localhostg // [文件名]。

你知道如何解决这个问题吗?

如果我更改配置变量以便显示相对子目录的内容,则此脚本可以正常工作。它还说$ Root变量可以位于webserver根目录之外。

此外,即使单击链接不起作用,右键单击并选择“目标另存为”也可以保存/下载文件。

(随意询问您是否需要更多信息):)

3 个答案:

答案 0 :(得分:5)

您的网络服务器无法看到DocRoot之外的文件,因此它无法通过带有直接链接的浏览器来提供文件。您需要使用readfile()将其内容打印到浏览器中并正确设置标题。

要使其工作,您需要更改indexer.php中的配置:

// this way it works with accentuated letters in Windows
$Root = utf8_decode("G:\test"); // define the directory the index should be created for (can also be located outside the webserver root)

$AllowDownload = TRUE; // enclose file items with the anchor-tag (only makes sense when the files are in the webserver root)
// you need to place download.php in the same directory as indexer.php
$WebServerPath = dirname($_SERVER['SCRIPT_NAME']) . "/download.php?path="; // path where the indexed files can be accessed via a http URL (only required when $AllowDownload is TRUE)

您必须在download.php所在的目录中放置一个名为indexer.php的新文件,其中包含以下内容:

<?php

// it must be the same as in indexer.php
$Root = utf8_decode("G:\test");

function checkFileIsInsideRootDirectory($path, $root_directory) {
    $realpath = realpath($path);

    if (!file_exists($realpath))
        die("File is not readable: " . $path);

    // detects insecure path with for example /../ in it
    if (strpos($realpath, $root_directory) === false || strpos($realpath, $root_directory) > 0)
        die("Download from outside of the specified root directory is not allowed!");
}

function forceDownload($path) {
    $realpath = realpath($path);

    if (!is_readable($realpath))
        die("File is not readable: " . $path);

    $savename = (basename($path));

    header("Pragmaes: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private", false);
    header("Content-type: application/force-download");
    header("Content-Transfer-Encoding: Binary");
    header("Content-length: " . filesize($path));
    header("Content-disposition: attachment; filename=\"$savename\"");

    readfile("$path");
    exit;
}

if (!isset($_GET['path']))
    die("Path not specified!");

$fullPath = $Root . $_GET['path'];

checkFileIsInsideRootDirectory($fullPath, $Root);

forceDownload($fullPath);

答案 1 :(得分:2)

您必须更改Apache配置。问题不在于PHP脚本,问题是网络服务器(除了你配置它之外,它不能在web root之外提供文件)。

在apache配置中尝试这样的事情:

Alias /testalias "G:/test"
<Directory "G:/test">
  Options Indexes FollowSymLinks MultiViews ExecCGI
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

当您访问http://localhost/testalias

时,这会告诉Apache提供来自G:/ test的文件

然后更改脚本配置:

$WebServerPath = dirname("testalias");

它应该有效!

答案 2 :(得分:1)

让我们来看看那个剧本:

$Root = realpath("."); // define the directory the index should be created for (can also be located outside the webserver root)
$AllowDownload = TRUE; // enclose file items with the anchor-tag (only makes sense when the files are in the webserver root)
$WebServerPath = dirname(getenv("SCRIPT_NAME")); // path where the indexed files can be accessed via a http URL (only required when $AllowDownload is TRUE)

注意“仅在文件位于Web服务器根目录中时才有意义”和“可通过http URL访问索引文件的路径”。这表示此脚本的设计不能够下载Web服务器根目录之外的文件。

但是,您可以修改此脚本,以便能够以styu在其答案中注明的方式执行此操作。然后,您可以将更改发送给脚本的作者。

顺便说一下,我在自己的服务器上测试了这个。