【问题标题】:Forcing PHP to download file via browser强制 PHP 通过浏览器下载文件
【发布时间】:2017-06-14 22:14:35
【问题描述】:

我目前正在尝试在用户的浏览器中进行文件下载,但到目前为止还无法实现。

我在 stackoverflow.com 上查看了其他答案,到目前为止还没有找到任何可以解决我问题的方法。

我的流程如下:

我创建文件名和文件路径,然后设置标题:

$date = new DateTime();
$currentDateTime = $date->format("Y-m-d H:i:s");
$filename = "{$name}_{$currentDateTime}.csv";
$filepath = $rootfull . "/{$filename}";

// Set headers
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="' . $filepath . '"');
header('Content-Length: ' . filesize($filepath)); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');

然后我创建文件并开始写入:

// Write header
fputcsv($output, $header);
fputcsv($output, array()); // Empty line

// Write column names
$column_headers = array_keys(array_flip($columns));

foreach ($data as $row)
{
    fputcsv($output, $row);
}

echo readfile($filepath);
die();

文件被生成并写入指定位置(在本例中为/var/www/<project>/<filename>.csv,但没有向用户表明发生了任何事情。没有下载对话框,什么都没有。

如果有人发现我的代码或流程存在问题,请指出并最好提出更好/替代的方法,此时欢迎任何帮助。

【问题讨论】:

  • 发送标题之前创建文件对吗?
  • 只是readfile($file_url); 没有echo
  • @ficuscr 在您尝试将读取文件返回给用户之前,您无需在发送标头之前创建文件。
  • 另外,你可以fopen('php://output', 'w') 打开php的输出流,然后fputcsv 到那个。然后,您不需要磁盘上的临时文件。这样,如果两个人同时尝试下载,您就会遇到问题。
  • @JonathanKuhn 是的,但是 Content-Length 0 然后

标签: php file download header


【解决方案1】:

如果写入磁盘没有好处(糟糕的缓存),那么可能会像这样写入缓冲区:

<?php

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="dump_' . date('Ymd') . '.csv"');
header("Pragma: no-cache");
header("Expires: 0");
$this->outputCSV($results);
exit(); //->

public function outputCSV($data, $useKeysForHeaderRow = true)
{
    if ($useKeysForHeaderRow) {
        array_unshift($data, array_keys(reset($data)));
    }
    $outputBuffer = fopen("php://output", 'w');
    foreach($data as $v) {
        fputcsv($outputBuffer, $v);
    }
    fclose($outputBuffer);
}
?>

【讨论】:

  • 感谢您的回复,但遗憾的是这没有什么区别 - 文件仍然没有在浏览器中下载。
  • 奇怪。从正在使用的代码中复制它。也许你的浏览器是问题。
  • 这是不可能的,不过还是谢谢你的回答,希望它对将来的人有所帮助:)
猜你喜欢
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2018-05-15
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多