【发布时间】:2013-04-10 19:10:51
【问题描述】:
我知道这个错误背后的理论,但它现在又让我发疯了。我在我的应用程序中使用Tonic。使用这个库,您可以将所有流量重定向到您的 dispatch.php 脚本,然后该脚本执行适当的 Resource 并且 Resource 返回一个由 dispatch.php 显示(输出)的 Response。
Response的输出方法如下:
/**
* Output the response
*/
public function output()
{
foreach ($this->headers as $name => $value) {
header($name.': '.$value, true, $this->responseCode());
}
echo $this->body;
}
所以 AFAIK 这告诉我们,您不能在 Resource 的 php 输出中写入任何内容。
我现在有一个Resource,它从输入的 csv 动态生成一个 csv 并将其输出到浏览器(它将 1 列数据转换为不同的格式)。
$csv = fopen('php://output', 'w');
// sets header
$response->__set('contentDisposition:', 'attachment; filename="' . $fileName . '"');
while (($line = fgetcsv($filePointer, 0, ",", '"')) !== FALSE) {
// generate line
fputcsv($csv, $line);
}
fclose($filePointer);
return $response;
这可以 100% 正常工作。标题没有问题,并且生成了正确的文件并提供下载。这已经很混乱了,因为我们在设置标头之前写入输出? fputcsv 实际上是做什么的?
我有第二个资源做类似的事情,但它输出自定义文件格式(文本文件)。
$output = fopen('php://output', 'w');
// sets header
$response->__set('contentDisposition:', 'attachment; filename="' . $fileName . '"');
while (($line = fgetcsv($filePointer, 0, ",", '"')) !== FALSE) {
// generate a record (multiple lines) not shown / snipped
fwrite($output, $record);
}
fclose($filePointer);
return $response;
唯一的区别是它使用 fwrite 而不是 fputcsv 和 bang
headers already sent by... // line number = fwrite()
这很混乱!恕我直言,在这两种情况下它实际上都应该失败吗?为什么第一个有效?我怎样才能让第二个工作? (我可以生成一个包含该文件的巨大字符串并将其放入响应正文中并且它可以工作。但是文件可能相当大(高达 50 mb),因此希望避免这种情况。)
【问题讨论】:
-
你不应该
fwrite到$response而不是$output吗? -
已知此类错误的答案stackoverflow.com/a/8028987
-
我知道这一点,正如我在问题中所说的那样,实际上可以防止这种 cmets。
标签: php file-io http-headers