2

在网页上,我正在使用以下代码将一些数据写入 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”已经进入 CSV 下载文件,而它已经有 fclose()?我想输出要在浏览器中显示的页面的其余 HTML。我怎样才能做到这一点?

4

4 回答 4

5

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&amp;id=123" />

这将在 3 秒后开始下载。

于 2014-04-14T09:38:15.227 回答
4

没有“CSV 文件”(还没有)。

您正在做的是将数据流发送到客户端,并告诉客户端该流具有 a Content-Typeoftext/csv和 a filenameof $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)您只关闭第二个文件句柄。

于 2014-04-14T09:49:06.173 回答
1

这里有一个非常古老的线程,但为了解决这个问题,我只添加了一个简单的 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();
}
于 2019-09-26T11:24:54.473 回答
0

采用

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!?
于 2014-04-14T09:38:54.563 回答