Php 禁止将具有内容处置标头的消息输出到文件

Php 禁止将具有内容处置标头的消息输出到文件,php,output,content-disposition,Php,Output,Content Disposition,当有人调用URL时,我想向他/她发布一个.csv文件。这适用于内容处置头。但是,我想在我的程序中告诉php什么时候应该从输出开始,什么时候应该忽略以其他方式打印到屏幕上的消息 原因是我调用了在数据库中查找数据的常规类(CRM)。这些查找函数“必须”生成一些输出。这是因为它们花费的时间超过1分钟(有时),并且输出就像“ping”命令浏览器不要关闭连接并等待脚本完成。 不过,我不希望在csv文件中显示此输出 <?php error_reporting(E_ERROR); header('Ex

当有人调用URL时,我想向他/她发布一个.csv文件。这适用于内容处置头。但是,我想在我的程序中告诉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()等来控制输出,但它不起作用。(我还试着去打扫卫生等)
我还认为只有写入$file的东西(php://output)写入csv文件,但它会将所有内容打印到csv文件中。

一种方法可以是显示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--
备选方案

还有更常用的基于JavaScript的方法。基本上原理是一样的:您执行一个初始请求,然后在后台开始生成。后续请求(例如AJAX或简单重新加载)要求使用临时ID获取数据


另一个更复杂的替代方案是使用真正的服务器推送功能实现双向websocket连接。

如果他们ping,他们是否会将ping发送到浏览器,即刷新输出?在这种情况下,只有重新设计应用程序才能对您有所帮助。JavaScript依赖和/或重新加载是一种选择吗?IE/Edge/Fox在长轮询时不应该有大问题,只有Opera报告有一些问题。“ping”是必要的,因为OrganizationLookups类等用于不同的“工具”,而不仅仅是csv文件摘要。但显然,没有简单的“技巧”来告诉应用程序是否将数据放入文件,因此我将在查找函数中使用一个“静默”参数。术语“ping”的实际含义是什么?因此,不清楚“ping”输出的是什么,也不清楚为什么要尝试通过缓冲来阻止输出。发送的数据应该会阻止浏览器关闭连接。我只是复制粘贴了你的标题,没有进一步检查其合理性,甚至覆盖了以前的标题。不确定,但我想对单个部件的缓存控制完全被忽略了。嗨,卡西莫多。对不起,我离线了。这正是解决我问题的方法。我会试试看它是否有效。很抱歉“ping”这个词不准确,但我不知道如何描述它,你猜对了,我的意思是什么;)您或其他人是否知道浏览器(如Chrome)是否支持这些多部分代理。当我现在调用页面时,我会将整个响应保存到一个文件中,并将URL中的文件部分作为其名称。响应的边界和标题看起来是正确的。2012年左右的论坛帖子表明,浏览器不支持多部分响应,但这可能已经改变了。第一部分中的“内容处置:呈现”也没有做出任何修改difference@user3117071你尝试了哪些浏览器?上述装置在fixefox中进行了测试,工作正常。标题和边界必须精确,即它们必须位于第0列,并且必须有带空行的CR+LF字符来分隔内容。RFC建议单个LF字符也应该被轻松地解释为换行符序列,大多数浏览者也遵守这一建议。LF(ASCII 10)是必需的。实际上chromium browser/debian似乎有问题(编辑器可能只保存了LF)。Fox的行为完全符合预期,Edge/IE未经测试。
<Files "multipart.php">
    php_value output_buffering Off
</Files>