在网页上,我使用以下代码将一些数据写入CSV文件,最后用fclose((关闭;
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$filename);
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
echo "HELLO WORLD"; // sneaks into CSV!?
为什么"HELLO WORLD"在已经fclose((的情况下进入CSV下载文件?我想输出要在浏览器中显示的页面的其余 HTML。我该怎么做?
在 1 个 HTTP 请求之后是 1 个响应。您不能同时发送内容类型text/csv
和内容类型text/html
(SPDY 可能是,但纯 HTTP 不是(。
fclose
关闭文件描述符,但不关闭浏览器的输出。
您还应该设置一个Content-Length
标题并输入文件大小。
马克贝克已经在评论中给出了最重要的一点:
echo
和写入php://output
会将内容放入同一流中:STDOUT
。其他选择是将CSV写入内存(但不使用它,则毫无意义(或文件。阅读有关这些流的更多信息:http://www.php.net/manual/en/features.commandline.io-streams.php
可能的解决方案:
您需要 2 个 HTTP 请求。 1 用于下载,另一个用于您的 HTML。最流行的方法是首先使用 HTML 响应并放入类似的东西
<meta http-equiv="refresh"
content="3; URL=http://yourserver.com/download.php?id=pdf&id=123" />
这将在 3 秒后开始下载。
目前还没有"CSV 文件"。
您正在做的是向客户端发送数据流,并告诉客户端此流具有text/csv
Content-Type
和filename
$filename
。 然后,客户端可以选择将其另存为 CSV 文件或仅在浏览器中显示。
此代码:
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
正在有效地做与echo $cvs_cols
相同的事情(用一些额外的东西来格式化 csv 输出(。
因此,当调用echo "HELLO WORLD";
时,它会以与$cvs_cols
变量内容相同的数据流发送。
当您调用fopen('php://output', 'w')
时,您将创建第二个文件句柄来php://output
因为默认情况下会创建一个句柄,以输出对echo
等的调用。因此,当您调用fclose($out)
时,您只会关闭第二个文件句柄。
这里有一个非常古老的线程,但为了解决这个问题,我只是添加了一个简单的 exit((; 命令。因此,一个按钮使用查询字符串"action=export_csv"调用同一页面,然后使用 exit(( 运行该操作;在最后一行,希望有帮助。
<a href="?action=export_csv">Export CSV</a>
那么页面上的"操作"是:
if(isset($_GET['action']) && $_GET['action']=='export_csv'){
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=email-responses.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('Email address'));
$db = new PDO('mysql:host=hostname_mysql;dbname=database_mysql;charset=UTF8', username_mysql, password_mysql);
$query = "SELECT XXX FROM XXXX";
$result = $db->query($query);
$data = $result->fetchAll(PDO::FETCH_ASSOC);
// loop over the rows, outputting them
foreach($data as $row){
fputcsv($output, $row);
}
fclose($output);
exit();
}
使用
ob_clean(( : ob_clean — 清理(擦除(输出缓冲区
flush(( : flush — 刷新输出缓冲区(flush(
ob_start();
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$filename);
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
ob_end_clean(); // the buffer and never prints or returns anything.
echo "HELLO WORLD"; // sneaks into CSV!?