服务器返回损坏的文件

时间:2014-06-18 12:25:03

标签: php nginx export attachment

我有一个脚本,它从数据库中获取数据并通过打印将其收集到PHP输出缓存(ob_start)中。刷新后,我得到提示保存文件。但文件并不总是需要长度。它的长度几乎总是160 Kb,但有时它的全长为15 Mb。我刚刚运行该脚本20次,20次3次,我的文件大小正常,在其他情况下,它具有相同的大小(160 538字节)。

为什么会发生这种情况?

我的代码的简短变体:

ob_start();
$offset = 0;
$count  = 20000;
while (true) {
    $dataFromMysql = GetMySqlData($count, $offset);
    foreach($dataFromMysql as $data) {
        print implode(';', $data);
    }

    if (!$dataFromMysql || count($dataFromMysql) < $count) {
        break;
    }

    $offset += $count;
}

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
header('Content-Type: application/csv');
header('Content-Length: ' . ob_get_length());
header('Content-Disposition: attachment; filename="export.csv"');
ob_end_flush();
exit;

网站位于两台物理服务器上。但我要求管理员将流程指向该脚本的主服务器。

2 个答案:

答案 0 :(得分:0)

您可以简单地写入字符串变量,而不是使用ob_ *函数,然后使用strlen()获取Content-Length,然后在结尾处打印出完整的字符串。

编辑: 可能更有用的是fputcsv(),您可以使用它来生成csv文件服务器端,并使用readfile()将其发送出去。

答案 1 :(得分:0)

我打败了它!

以下是工作代码的简短变体:

header('Content-Description: File Transfer');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Transfer-Encoding: chunked');
header('Pragma: public');
header('Expires: 0');
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename="export.csv"');
header('Cache-Control: max-age=0');

$outputString = '';
$offset = 0;
$count  = 20000;
while (true) {
    $dataFromMysql = GetMySqlData($count, $offset);
    foreach($dataFromMysql as $data) {
        $outputString .= implode(';', $data);
    }

    if (!$dataFromMysql || count($dataFromMysql) < $count) {
        break;
    }

    $offset += $count;
}

$contentLength = strlen($outputString);
header('Content-Length: ' . $contentLength);

$hFile = fopen('php://output', 'wb+');
if ($hFile) {
    for ($i=0; $i<$contentLength; $i++) {
        fwrite($hFile, $this->outputString[$i]);
    }
    fclose($hFile);
}

exit;

我不知道为什么,但它现在有效!仅仅因为我输出完整的收集字符串一个字符(1个字节)。我尝试输出1Kb(1024字节),但它不起作用:(

$hFile = fopen('php://output', 'wb+');
if ($hFile) {
    for ($i=0; $i<$contentLength; $i++) {
        fwrite($hFile, $this->outputString[$i]);
    }
    fclose($hFile);
}

我希望它会帮助某人;)