为什么PHP在fclose()之后继续输出到CSV文件?

为什么PHP在fclose()之后继续输出到CSV文件?,php,fclose,Php,Fclose,在一个网页上,我使用下面的代码将一些数据写入CSV文件,最后使用fclose()关闭 为什么“HELLO WORLD”已经包含fclose()了,却进入了CSV下载文件?我想输出要在浏览器中显示的页面的其余HTML。我该怎么做呢?在一个HTTP请求之后是一个响应。您不能同时发送内容类型text/csv和内容类型text/html(可以使用,但不能使用纯HTTP) fclose关闭文件描述符,但不关闭浏览器的输出 您还应该设置内容长度标题并放入文件大小 马克·贝克在评论中已经给出了最重要的一点:

在一个网页上,我使用下面的代码将一些数据写入CSV文件,最后使用fclose()关闭


为什么“HELLO WORLD”已经包含fclose()了,却进入了CSV下载文件?我想输出要在浏览器中显示的页面的其余HTML。我该怎么做呢?

在一个HTTP请求之后是一个响应。您不能同时发送内容类型
text/csv
和内容类型
text/html
(可以使用,但不能使用纯HTTP)

fclose
关闭文件描述符,但不关闭浏览器的输出

您还应该设置
内容长度
标题并放入文件大小

马克·贝克在评论中已经给出了最重要的一点:

echo
和写入
php://output
将内容放入同一流:。其他选项是将CSV写入内存(但如果不使用它,它将毫无意义)或文件。阅读有关这些流的更多信息:

可能的解决方案:

您需要2个HTTP请求。1用于下载,另一个用于HTML。最流行的方法是首先使用HTML响应,然后在

<meta http-equiv="refresh"
      content="3; URL=http://yourserver.com/download.php?id=pdf&amp;id=123" />

这将在3秒钟后开始下载。

使用

ob_clean():ob_clean-清除(擦除)输出缓冲区

flush():flush-刷新输出缓冲区()


还没有“CSV文件”。

您要做的是向客户端发送数据流,并告诉客户端该流的
内容类型为
text/csv
,文件名为
filename
。然后,客户机可以选择将其保存为CSV文件,或仅在浏览器中显示

此代码:

$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
有效地做了与echo$cvs\u cols
相同的事情(使用一些额外的东西来格式化csv输出)

因此,当有人呼叫
echo“HELLO WORLD”时
它与
$cvs\u cols
变量的内容以相同的数据流发送


当您调用
fopen('php://output“,”w“
您正在为
php://output
由于默认情况下会创建一个,以便将调用输出到
echo
等。因此,当您调用
fclose($out)时
您只关闭了第二个文件句柄。

这里有一个非常旧的线程,但为了解决这个问题,我只添加了一个简单的exit();指挥部。因此,一个按钮使用“action=export_csv”的查询字符串调用同一页面,然后使用exit()运行该操作;在最后一行,希望这能有所帮助

<a href="?action=export_csv">Export CSV</a>

“HELLO WORLD”实际上是我想要发送到浏览器的HTML,但正如我所说的,它们会进入CVS文件。虽然您没有重新发送输出,但由于文档仍由正在执行的PHP代码构建,因此回音的内容将附加到CSV。它不会继续输出到CSV,但是因为你在写你的csvphp://output 而回声也会去php://output,然后这两个函数将位于同一个位置fclose()关闭文件写入函数的文件句柄,如fwrite()、fputcsv()等。。。。但是php://output 也是回声、打印等的标准输出流。。。。这相当于必须为同一个文件设置文件句柄,并且您只关闭其中一个。您不能在同一个请求中同时发送HTML响应和CSV(或任何其他文件类型)响应。谢谢,良好的链接和说明。起初我没有意识到只有一个输出流,现在我可以清楚地看到它。
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
<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();
}