根据经验,似乎在收到以Content-Disposition:附件标题为特色的回复时,不同的浏览器会在以下时刻显示文件下载对话框:
> Firefox会在收到标题后立即显示该对话框
> Internet Explorer一旦收到标题加上响应正文的255个字节,就会显示该对话框.
> Chromium在收到标题加上响应正文的1023个字节后显示对话框.
那么,我们的目标如下:
>尽快将响应正文的第一个千字节刷新到浏览器,以便Chrome用户尽早看到文件下载对话框.
>此后,定期向浏览器发送更多内容.
阻碍这些目标的可能是多级缓冲,您可以尝试以不同的方式进行战斗.
PHP的output_buffer
如果将output_buffering设置为Off以外的值,PHP将自动创建一个输出缓冲区,用于存储脚本尝试发送到响应主体的所有输出.您可以通过确保从php.ini文件或从apache.conf或nginx.conf等Web服务器配置文件中将output_buffering设置为Off来防止这种情况发生.或者,您可以使用ob_end_flush()或ob_end_clean()在脚本开头关闭输出缓冲区(如果存在):
if (ob_get_level()) {
ob_end_clean();
}
您的网络服务器完成缓冲
一旦输出超过PHP输出缓冲区,它可能会被您的网络服务器缓冲.您可以通过定期调用flush()(例如每100行)来尝试解决这个问题,尽管PHP手册对提供任何保证犹豫不决,列出了可能失败的特定情况:
flush
…
Flushes the write buffers of PHP and whatever backend PHP is using (CGI, a web server, etc). This attempts to push current output all the way to the browser with a few caveats.
flush() may not be able to override the buffering scheme of your web server …
Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.
Server modules for Apache like mod_gzip may do buffering of their own that will cause flush() to not result in data being sent immediately to the client.
每次尝试回显任何输出时,你都可以通过在脚本开头调用ob_implicit_flush自动调用flush() – 但要注意,如果你通过一个尊重flush()调用的机制启用了gzip,比如Apache的mod_deflate模块,这种常规刷新将削弱其压缩尝试,并可能导致您的“压缩”输出比未压缩时更大.因此,对于某些适度但非微小的n,每n行输出显式调用flush()可能是更好的做法.
把它们放在一起,然后,你应该调整你的脚本看起来像这样:
if (ob_get_level()) {
ob_end_clean();
}
$csv = 'title.csv';
header( "Content-Type: text/csv;charset=utf-8" );
header( "Content-Disposition: attachment;filename=\"$csv\"" );
header( "Pragma: no-cache" );
header( "Expires: 0" );
flush(); // Get the headers out immediately to show the download dialog
// in Firefox
$array = get_your_csv_data(); // This needs to be fast, of course
$fp = fopen('php://output', 'w');
fputcsv($fp, array_keys($array), ';', '"');
foreach ($array as $i => $fields)
{
fputcsv($fp, $fields, ';', '"');
if ($i % 100 == 0) {
flush(); // Attempt to flush output to the browser every 100 lines.
// You may want to tweak this number based upon the size of
// your CSV rows.
}
}
fclose($fp);
?>
如果这不起作用,那么我认为您无法通过PHP代码尝试解决问题 – 您需要弄清楚是什么导致您的Web服务器缓冲输出并尝试使用它来解决问题您的服务器的配置文件.