【问题标题】:Forcing download from server in php [duplicate]在php中强制从服务器下载[重复]
【发布时间】:2012-10-17 18:15:57
【问题描述】:

可能重复:
forcing a file download with php
force download of different files

我正在尝试允许用户从我的网站以 php 下载图像。我看过很多关于它的文章,我试图使用 php 文档中的readfile。但我似乎无法让它工作。

这是我尝试设置以开始下载的按钮的代码:

        <!-- download image button  -->
    <form class="grid_12" style="text-align: center;" action="../includes/download.php" method="post">
        <input type="hidden" name="id" value="<?php echo $photo->id; ?>" />
        <input type="hidden" name="img" value="<?php echo $photo->filename; ?>" />
        <?php if(isset($_GET['cat'])){?>
            <input type="hidden" name="cat" value="<?php echo $_GET['cat']; ?>" />
        <?php } ?>  
        <div id="download"><input type="submit" name="submit" value="Download Photo" /></div>
    </form>

这是我在 download.php 文件中设置的代码(redirect_to 只是一个调用 header(Location: var) 的函数,其中 var 是您传入的内容。

<?php
require_once('initialize.php');
?>
 <?php
header("Content-type: application/force-download; filename=".$_POST['img']);

// Force download of image file specified in URL query string and which
// is in the same directory as this script:
if(!empty($_POST['img']))
{
   $file = $_POST['img'];
   if (file_exists($file)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename='.basename($file));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        exit;
    }

   $addy = "../public/photo.php?id=".$_POST['id'];
   if(isset($_POST['cat'])){
        $addy .= "&cat=".$_POST['cat'];
   }
   redirect_to($addy);
}
header("HTTP/1.0 404 Not Found");
?> 

我在帖子中发送的隐藏变量主要用于重定向,以便在下载开始后将用户带回他们下载的页面。在我的本地主机上,我被重定向到单击下载按钮的页面。在我的服务器上,我只是被发送到一个注册为 download.php 的空白页面。我认为这可能与输出缓冲有关,因为我得到一个空白页。这通常意味着在我调用 header() 函数之前有某种输出。

如果有人能给我一些关于我在这里做错了什么的见解,我将不胜感激,感谢阅读。

-艾伦

【问题讨论】:

  • 做ob_start();在下载文件的顶部
  • 您的脚本可能容易受到path traversal 的攻击,它允许读取您服务器上的任何文件。
  • 您将 Content-Type: 标头设置了两次,我不太确定 RFC 是怎么说的……您可能想先检查一下。
  • 您应该将文件的绝对路径提供给 readfile()。只有你给了文件名吗?
  • 感谢所有快速回复,我会调查你们所有人所说的。阿曼,我想过这个,但我很好奇输出在哪里。 hakre,我确实有 2 个标题,我想我查了一下有人说要这样设置的地方。 Gumbo,我不认为它容易受到路径遍历的影响,因为我使用的是 post not get,并且帖子的所有值都是由页面的照片生成的。他们唯一能做的就是改变照片,但我认为他们不能从我的服务器上下载任何东西(据我所知)。 GBD,我试试绝对路径,看看效果如何。

标签: php download readfile


【解决方案1】:

感谢您的洞察力,我相信这是 hakre 和 GBD 指出的结合。我调用了标题两次,因为我设置了一个我看到的示例设置它的方式。然后我也将 php doc 中的示例用于 readfile...

然后我必须修复图像文件的绝对路径,因为我只发送文件名。再次感谢您的快速帮助,我非常感谢。

**更新

这在我的本地主机上为我解决了所有问题,但在服务器上,它现在将我带到一个充满乱码的页面,而不是开始下载......我会调查这个问题并在找到解决方案时重新发布。

**修复

首先我必须进入服务器上的 php.ini 文件并更改 allow_url_fopen = On 以便服务器可以使用 readfile、fopen 等文件方法。然后我还必须在文件上添加输出缓冲,因为那里有这么多的标题电话。没有输出缓冲,第一个是在整个调用建立之前调用的。

再次感谢所有帮助,它现在可以在我的本地主机和服务器上运行。

【讨论】:

    猜你喜欢
    • 2012-03-03
    • 2012-07-17
    • 2011-01-07
    • 2012-08-03
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    相关资源
    最近更新 更多