4

我尝试将数据从数据库导出到 .csv。当我单击导出链接时,如果数据量很大,我很长一段时间都看不到浏览器中的保存窗口。如果脚本看起来像挂了一段时间并且在很长一段时间后可以在浏览器中看到保存窗口,那可能会很混乱。代码在控制器中是这样的:

$this->_helper->layout->disableLayout();
        $this->_helper->viewRenderer->setNoRender();
        $fileName = $list->list_name . '.csv';

        $this->getResponse()->setHeader('Content-Type', 'text/csv; charset=utf-8')
                            ->setHeader('Content-Disposition', 'attachment; filename="'. $fileName . '"');      

        $contacts = new Contact();
        $contacts->export($listId);

导出方法一一读取记录并打印如下:

    $fp = fopen('php://output', 'w');        
    foreach ($mongodbCursor as $subscriber) {
           $row = formRow($subscriber);
       fputcsv($fp, $row);
        }       

我在一些保存 winow 的应用程序上看到几乎立即出现,当您单击保存时,您会看到下载进度。

我试图替换:

    $this->getResponse()->setHeader('Content-Type', 'text/csv; charset=utf-8')
                        ->setHeader('Content-Disposition', 'attachment; filename="'. $fileName . '"');

有了这个:

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="'. $fileName . '"');

到目前为止它没有帮助。我想知道是否可以在从数据库中一一读取所有数据之前发送标头?感谢您的协助。

4

6 回答 6

1

嗯我不熟悉 php://output,我的应用程序用 fopen,fwrite,fclose 将我的信息写入一个临时文件,然后我用类似的 header(); 选项。

            $filesize = filesize("tmp/export.csv");
            header("Content-Type: text/csv");
            header("Content-Disposition: attachment; filename=\"export.csv\"");
            header("Conent-Length: $filesize");
            readfile("tmp/export.csv");
            unlink("tmp/export.csv");
            exit;

这会立即提供您浏览器的下载窗口。

于 2012-04-12T06:56:22.497 回答
1

你可以尝试这样做:

  • 调用标头函数而不是$this->getResponse()->setHeader()(响应内容可能保存在缓冲区中并仅在完成时输出 - 导出完成的时间)
  • 尝试直接回显内容而不是写入 php://output(如果您在此之前设置标题,您回显的所有内容都将放在生成的 CSV 文件中)

编辑

替换为如下fputcsv函数print_row

function print_row($row) {
        echo '"' . implode('","', $row) . '"' . "\r\n"; 
}

该函数将第一个参数作为数组获取,添加"和回显,到内容。

于 2012-04-12T06:58:57.903 回答
0

您的函数可能希望在 long 操作之前调用 flush / ob_flush 并让 HTTP 标头在 long 过程之前发送给客户端。

于 2013-01-04T01:53:17.063 回答
0

尝试在你的价值中使用application/force-download而不是。text/csvContent-Type

header("Content-Type: application/force-download; name=\"" . $fileName . "\""); 

这将强制一个实际的下载框,而不是仅仅浏览器中显示内容。

以下是MIME Application的一些文档:

Mime application/force-download,通常表示为 mime application/x-force-download,通常与 PHP 代码结合使用以触发下载框,而不是用于在 Web 浏览器中显示内容。

例如,如果您的网站上有一个文件,您希望用户下载而不是在 Web 浏览器中查看,您可以在文件的标题内容类型字段中输入适当的 mime 应用程序/强制下载代码。请注意,mime application/force-download 不是已注册的 MIME 类型。此外,在 PHP 代码中使用时,mime application/force-download 的首选拼写包含“x-”前缀。

于 2012-04-12T15:52:32.503 回答
0
// $file = path of file

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;

来源: http: //php.net/manual/en/function.readfile.php

于 2012-04-12T07:10:31.507 回答
0

我不知道这是否是一个好的解决方案,我没有进行太多探索,但似乎它正在工作。在我将一些数据添加到标头之后的缓冲区之后,在导出之前,它会控制它。

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="'. $fileName . '"');

    echo str_pad('', ini_get('output_buffering'));      
    ob_flush();
    flush();

    Model_Subscriber1::exportList($listId);

为了让它在控制器中工作,我在 Zend Bootstrap.php 中添加了:

/**
 * hint to the dispatcher that it should not use output buffering to capture output generated by action controllers.
 *  By default, the dispatcher captures any output and appends it to the response object body content. 
 */
protected function _initFront()
{
    $frontController = Zend_Controller_Front::getInstance();
    $frontController->setParam('disableOutputBuffering', 1);        
}

在这种情况下,我在浏览器中快速获取下载窗口,然后导出数据,这可能需要很长时间。我不知道这个解决方案现在是否可以接受。我很乐意在这里发表您对此的看法。它会导致将空数据添加到导出文件时出现问题。因此,我将其更改为控制器。

    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="'. $fileName . '"');

    Model_Subscriber1::exportList($listId);

并将 chang 函数导出为如下所示:

  foreach ($mongodbCursor as $subscriber) {
           $row = formRow($subscriber);
    echo '"' . implode('","', $row) . '"' . "\r\n";
    ob_flush();
    flush();                    

  }       
于 2012-04-20T11:26:35.343 回答