将带有Content-Disposition标头的消息隐藏到文件输出

时间:2019-01-06 17:21:59

标签: php output content-disposition

当某人调用URL时,我想向他/她发布一个.csv文件。这适用于Content-Disposition标头。但是,我想在程序中告诉php什么时候应该以输出开头,什么时候应该忽略以其他方式打印到屏幕上的消息。

原因是我正在调用在数据库(CRM)中查找数据的常规类。这些查找功能“必须”生成一些输出。原因是它们花费了超过1分钟的时间(有时),并且输出就像一个“ ping”,告诉浏览器不要关闭连接并等待脚本完成。 不过,我不希望此输出出现在我的csv文件中。

<?php
error_reporting(E_ERROR);

header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=search.csv');
....
ob_start();

//these two methods can take a long time and they 'ping' between pages
//i.e. after they looked up 450 records, they ping and look up the next 450
$allPublished=OrganizationLookups::lookup(["ORGANISATION_FIELD_4" => 
    "true"],$myInsightly);
$allContacts=ContactLookups::lookup(["TAGS" => "TPZ-Mieter"],$myInsightly);
//flush and ob_end_clean was my idea to suppress the output
//but it does not work
flush();ob_flush();
ob_end_clean();

//now i am ready to put everything to the file what comes next
$file = fopen('php://output', 'w');
....
   fputcsv($file,$itarray); //in foreach loop
}
fclose($file);
exit();
?>

正如您在代码中看到的那样,我试图摆弄ob_start()等来控制输出,但是它不起作用。 (我也尝试过ob_get_clean等) 我也认为只有写入$ file(php:// output)的内容才写入csv文件,但是它将所有内容打印到其中。

1 个答案:

答案 0 :(得分:0)

一种方法可以是显示HTML页面并提供文件下载的分段答复。但是,某些浏览器(尤其是Chrome)似乎存在支持问题。

<?php  declare (strict_types=1);
  header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
  header('Cache-Control: no-store, no-cache, must-revalidate');
  header('Cache-Control: post-check=0, pre-check=0', FALSE);
  header('Pragma: no-cache');
  header('Content-type: multipart/mixed; boundary="MultiPartBoundary"');
?>

--MultiPartBoundary
Content-type: text/html; charset=UTF-8

<!DOCTYPE html>
<html>
<head>
  <title>Download</title>
  <meta charset="UTF-8">
</head>

<body>
  <h1>search.cvs - Download</h1>
  <div>
    generating CVS
<?php  // fake generation showing progress
  for($i=0; $i<10; $i++)
  {
    sleep(1);
    echo '.' . str_repeat(' ', 1024), PHP_EOL;
    flush();
  }
?>
  </div>
</body>
</html>
--MultiPartBoundary
Expires: Sun, 01 Jan 2014 00:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Content-type: text/csv; charset=utf-8
Content-Disposition: attachment; filename=search.csv

<?php   // CVS output
echo <<< __EOS__
Col1,Col2,Col3
Val11,Val12,Val13
Val21,Val22,Val23

__EOS__;
?>

--MultiPartBoundary--

我使用.htaccess禁用缓冲

<Files "multipart.php">
    php_value output_buffering Off
</Files>

替代

有更多基于JavaScript的常用方法。基本上,原理总是相同的:执行一个启动请求,然后在后台开始生成。后续请求,例如AJAX或简单的重新加载,要求提供带有临时ID的数据。

另一个更复杂的选择是使用真正的服务器推送功能来实现双向Websocket连接。