正如我在埃德森的答案的評論中提到,我預期「已經發送了頭」在代碼的最後一行警告:
header('Content-Length: '.$streamSize);
因爲輸出在此之前寫頭被髮送,但他的例子工作正常。
一些調查使我對以下結論:
在您使用的輸出緩衝器(weither用戶的一個或 默認PHP),你可以發送HTTP標頭和內容的方式時你想要 。您知道任何協議都需要在主體 (因此術語「標題」)之前發送標題,但是當您使用輸出緩衝層時,PHP 將爲您處理此問題。任何使用輸出 頭(header(),setcookie(),session_start())的PHP函數實際上都將使用 內部的sapi_header_op()函數,該函數僅填充緩衝區的頭部 。當你使用printf()寫入輸出時,它將輸出緩衝區寫入 (假設一個)。 當發送輸出緩衝區爲 時,PHP開始首先發送標題,然後開始發送標題。 PHP 照顧你的一切。如果你不喜歡這種行爲,你可以使用 來禁用任何輸出緩衝層。
下大多數配置
和
PHP的緩衝區的默認大小爲4096個字節 (4KB),這意味着PHP緩衝器可以保持數據高達4KB。 一旦超過此限制或PHP代碼執行完成,緩衝內容 自動發送到到任何後端PHP正在使用(CGI, mod_php,FastCGI)。輸出緩衝在PHP-CLI中始終爲Off。
Edson的代碼工作,因爲輸出緩衝區沒有自動刷新,因爲它沒有超過緩衝區大小(並且在發送最後一個報頭之前腳本未明顯終止)。
只要輸出緩衝區中的數據超過緩衝區大小,就會引發警告。或者在他的例子中,當數據爲
$get_users_stmt->fetch(PDO::FETCH_ASSOC)
太大。
爲了防止出現這種情況,您應該使用ob_start()和ob_end_flush()來管理輸出緩衝。如下所示:
// Turn on output buffering
ob_start();
// Define handle to output stream
$basic_info = fopen("php://output", 'w');
// Define and write header row to csv output
$basic_header = array('Header1', 'Header2');
fputcsv($basic_info, $basic_header);
$count = 0; // Auxiliary variable to write csv header in a different way
// Get data for remaining rows and write this rows to csv output
while($user_row = $get_users_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($count == 0) {
// Write select column's names as CSV header
fputcsv($basic_info, array_keys($user_row));
} else {
//Write data row
fputcsv($basic_info, $user_row);
}
$count++;
}
// Get size of output after last output data sent
$streamSize = ob_get_length();
//Close the filepointer
fclose($basic_info);
// Send the raw HTTP headers
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=test.csv');
header('Expires: 0');
header('Cache-Control: no-cache');
header('Content-Length: '. ob_get_length());
// Flush (send) the output buffer and turn off output buffering
ob_end_flush();
不過,你仍然受到其他限制。
如果您寫入輸出緩衝區,您將立即將其發送到客戶端。在這種情況下,首先需要發送任何頭文件。 – datasage
ob_clean()是沒有意義的,除非你在某處完成了ob_start()。並考慮讀取文件WRITES輸出,但你正在閱讀該輸入。除非你在所有這些代碼之前完成了ob_start(),否則你的fputcsv()已經寫入輸出並且在任何頭文件代碼被執行之前都轉到瀏覽器。 –
只要使用「@」可以證明正確,我就可以從字面上命名PHP中的一種方法。它不在你的代碼中,所以你可以在開始時正確地編寫你的代碼嗎? –