将带有 Content-Disposition header 的消息抑制到文件输出
Suppress messages with Content-Disposition header to file output
当有人调用 URL 时,我想 post him/her .csv 文件。这适用于 Content-Disposition headers。但是,我想在我的程序中告诉 php 什么时候应该从输出开始,什么时候应该忽略以其他方式打印到屏幕上的消息。
原因是我调用一般 类 在数据库(CRM)中查找数据。这些查找函数 'must' 生成一些输出。这样做的原因是它们花费的时间超过 1 分钟(有时)并且输出类似于 'ping' 告诉浏览器不要关闭连接并等待脚本完成。
不过,我不希望在我的 csv-file 中出现此输出。
<?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();
?>
正如您在代码中看到的,我试图用 fiddle 和 ob_start() 等来控制输出,但它不起作用。 (我也试过 ob_get_clean 等)
我也认为只有写入 $file (php://output) 的内容才会写入 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--
我使用 .htaccess
禁用缓冲
<Files "multipart.php">
php_value output_buffering Off
</Files>
备选方案
有更多基于JavaScript的常用方法。基本上原则总是一样的:你执行一个发起请求,生成在后台开始。后续请求,例如AJAX或简单的重载,请求临时ID的数据。
另一个更复杂的替代方案是使用真正的服务器推送功能实现双向 websocket 连接。
当有人调用 URL 时,我想 post him/her .csv 文件。这适用于 Content-Disposition headers。但是,我想在我的程序中告诉 php 什么时候应该从输出开始,什么时候应该忽略以其他方式打印到屏幕上的消息。
原因是我调用一般 类 在数据库(CRM)中查找数据。这些查找函数 'must' 生成一些输出。这样做的原因是它们花费的时间超过 1 分钟(有时)并且输出类似于 'ping' 告诉浏览器不要关闭连接并等待脚本完成。 不过,我不希望在我的 csv-file 中出现此输出。
<?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();
?>
正如您在代码中看到的,我试图用 fiddle 和 ob_start() 等来控制输出,但它不起作用。 (我也试过 ob_get_clean 等) 我也认为只有写入 $file (php://output) 的内容才会写入 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--
我使用 .htaccess
禁用缓冲
<Files "multipart.php">
php_value output_buffering Off
</Files>
备选方案
有更多基于JavaScript的常用方法。基本上原则总是一样的:你执行一个发起请求,生成在后台开始。后续请求,例如AJAX或简单的重载,请求临时ID的数据。
另一个更复杂的替代方案是使用真正的服务器推送功能实现双向 websocket 连接。