【问题标题】:Downloaded file is made of Content-type header instead of actual file content下载的文件由 Content-type 标题而不是实际文件内容组成
【发布时间】:2014-10-06 06:47:16
【问题描述】:

[注意。主要编辑:同样的问题,但有更多信息]

我正在尝试创建一个 PHP 脚本,

  1. 生成 .xlsx 文件
  2. 邀请用户下载。

第 1 部分没问题(服务器上生成的文件是正确的)。第 2 部分不是。

我有两个文件来完成这项工作。第一个是XLSXExport.php,代码如下:

<?php
function exportDataToXLSX()
{
   require_once(dirname(__FILE__)."/_inc/lib/PHPExcel/Classes/PHPExcel.php");
   require_once(dirname(__FILE__)."/_inc/lib/PHPExcel/Classes/PHPExcel/Writer/Excel2007.php");

   $outputFileName = 'query.xlsx'; //TODO hash pour le nom
   $outputFilePath = dirname(__FILE__).'/_store/'.$outputFileName;
   $outputFileType = 'Excel2007';

   //Creates a PHPExcel object
   $objPHPExcel = new PHPExcel();

   //– Les Données
   $objPHPExcel->setActiveSheetIndex(0);
   $activeSheet = $objPHPExcel->getActiveSheet();
   $activeSheet->setCellValueByColumnAndRow(1, 1, "Test");

   //– On sauvegarde notre fichier (Format Excel 2007)
   $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
   $objWriter->save($outputFilePath);

   header("Content-Disposition: attachment; filename=\"" . basename($outputFilePath) . "\"");
   header("Content-Type: application/force-download");
   header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8');
   header("Content-Length: " . filesize($outputFilePath));
   header("Connection: close");

   @readfile($outputFilePath);
   exit();
}

exportDataToXLSX();
?>

第二个文件只包含第一个文件:

<?php
   require_once('XLSXExport.php');
?>

当我启动第一个文件时,一切顺利:我被要求保存/打开一个 xlsx 文件,该文件在右侧单元格中具有“测试”值。

当我启动第二个文件时,我被要求打开/保存的文件不知何故是一个损坏的文件,似乎是由发送的 HTML 标头组成的。

此处提供了一个输出文件示例(不是来自这个最小示例,而是来自制作最小示例的原始文件):https://mega.co.nz/#!HgpVDSAZ!tIYORzqX8GkFqiRQgWNTH_0J8zC0JyBfSLVejskqh-E

代码有什么问题?

【问题讨论】:

  • 所有的标题或只是其中的一些?
  • 我不知道。我已将 .csv 文件的链接添加到问题中,以获取保存损坏的下载文件。
  • 我已经用一个最小(非)工作示例编辑了这个问题。

标签: php http-headers content-type


【解决方案1】:

这个问题可能是因为 apache/php 在你的标题之前向浏览器发送“一些东西”。 在 php 标签之前/之后,您的第二个文件中是否有任何空字符?

你应该看看你的error_log,检查php是否抱怨无法发送标头。

另外,如果 output_buffering 开启,请尝试将其关闭(如果开启,php 不会在 header 之前抱怨输出,但“空”字符将在 header 之后发送,导致文件损坏下载)

【讨论】:

  • 禁用 output_buffering 确实是个好主意,因为当它打开时我没有看到错误消息。一旦我重新获得足够的声誉,我会投票给你的答案:)
【解决方案2】:

最后更新:

我想我设法重现了您的错误。这是我遇到的错误

Excel 无法打开文件“test.xlsx”,因为文件格式或文件 扩展无效。验证文件没有损坏 并且文件扩展名与文件的格式匹配。

这是文件的内容;如您所见,与您获得的内容相同。

首先,制作两个全新的文件;第一个文件的内容来自这里http://ideone.com/GVVPVb,而第二个文件的内容在这里http://ideone.com/9rVueZ。首先不要添加任何其他行。运行它,一切都会好起来的。

换句话说,您可能在&lt;?php 之前或?&gt; 之后有一个空格,一个UTF-8 字节顺序标记,可能是以前的错误、警告或通知,像print、@987654327 这样的函数@、echovar_dump&lt;?php 代码之前的任何原始&lt;html&gt; 区域或在&lt;?php 代码之前产生输出的任何内容。


[以前的编辑]

试试这样的(刚刚测试过)

header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=\"" . basename($filename) . "\"");
header("Content-Type: application/force-download");
header("Content-Length: " . filesize($filename));
header("Connection: close");

@readfile($filename); // or try echo $filename; 
exit();

也可以添加以下之一,但即使没有它们也可以使用

header("Content-Type: application/octet-stream");
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8');

您可以添加以下内容以防止从 Cashe 加载(IE 案例)

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

编辑:

由于您的输出实际上是一个 CSV 文件,您可以像这样使用fputcsv() 构建它

build_csv(array(
    array("data 1", "data 2", "data 3", "data 4"),
    array("data 2", "data 2", "data 2", "data 4")
));

function build_csv($buffer) {
    $output = fopen("php://output", "w");
    foreach ($buffer as $row) {
        fputcsv($output, $row);
    }
    fclose($output);
}

【讨论】:

  • 任何组合或这些标题组对我来说都是同样的问题。
  • @Silverspur 这是我做过数百次的事情;但是,我更新了答案,请尝试一下。
  • 我并没有说你的代码是错误的,我只是观察到在我的上下文中测试它时它不起作用。错误肯定在其他地方,隐藏在我没有提到的东西中,因为认为它无关紧要。不,我生成(并期望下载)确实是一个 xlsx 文件;我已经发布了 .csv,因为它是 LibreOffice 在保存损坏的文件时建议的默认格式。无论如何,感谢您的更新。
  • @Silverspur 既然你不接受答案,我猜你还在为这个问题苦苦挣扎,对吧? :)
  • 是的,我已经用一个最小的例子更新了这个问题。似乎问题来自于生成+标头代码包含在另一个 php 文件中的事实。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
相关资源
最近更新 更多