PHPExcel下载

80

大家好,我是phpexcel的新手。我想知道是否有一种方法可以将我创建的Excel文件直接发送给客户端下载,而不必在我的服务器上保存或在他下载后立即删除它。

我正在尝试在页面上创建一个“导出按钮”,当用户点击该按钮时会弹出一个包含我刚刚创建的Excel文件的窗口。

现在,在我创建表格后,我执行以下操作:

$objXLS->getActiveSheet()->getColumnDimension("A")->setAutoSize(true);
$objXLS->getActiveSheet()->getColumnDimension("B")->setAutoSize(true);

$objXLS->getActiveSheet()->setTitle('Test Stats');

$objXLS->setActiveSheetIndex(0);

$objWriter = PHPExcel_IOFactory::createWriter($objXLS, 'Excel5');
$objWriter->save(__DIR__."/test1.xls");

但是这会将它保存到我的服务器

谢谢你

8个回答

173

将它保存到 php://output­Docs 而不是保存到文件中:

$objWriter->save('php://output');

这将原样发送给浏览器。
你需要先添加一些headers­文档,就像在文件下载中常见的那样,以便浏览器知道该文件的类型和应如何命名(文件名):
// We'll be outputting an excel file
header('Content-type: application/vnd.ms-excel');

// It will be called file.xls
header('Content-Disposition: attachment; filename="file.xls"');

// Write file to the browser
$objWriter->save('php://output');

首先处理表头,然后保存。关于Excel表头,请参见以下问题:设置Excel文档的MIME类型


1
我正在尝试下载一个文件,但它不是我创建的那个。当我执行 $objWriter->save('php://output') 时,它会破坏我的整个页面 =\ - Dvir Levy
2
请注意,您在该页面上输出的唯一内容是两个header行和->save()操作的输出。您需要决定是显示页面还是提供下载。这两种情况都不容易用一个脚本实现。但是,您可以为下载创建一个脚本,为页面创建另一个脚本,并在执行页面脚本后重定向到下载脚本,该脚本将使浏览器提供"另存为"对话框。 - hakre
Dvir - 在你的URL中使用&format=raw。在你的MVC中,创建一个view.raw.php文件。 - MSD
1
当使用 php://output 时,您如何设置 Content-Length 标头? - tonix
@tonix:通常情况下,您需要它的字节数。要么$objWriter已经为您提供了它,要么您需要跟踪输出站点。在这种情况下,您可能希望首先将其输出到模板文件中,获取文件的大小,然后再流式传输到浏览器。 - hakre
显示剩余5条评论

22
$excel = new PHPExcel();
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="your_name.xls"');
header('Cache-Control: max-age=0');

// Do your stuff here

$writer = PHPExcel_IOFactory::createWriter($excel, 'Excel5');

// This line will force the file to download
$writer->save('php://output');

你好,感谢你的回答。我加了代码行 $writer->save('php://output'); 但它不会下载文件,反而输出一些垃圾数据到页面上。你知道为什么会这样吗? - Dvir Levy
你也设置了头部吗? - matino
我正在尝试使用PHPPowerpoint构建PPT,按照提到的步骤进行操作,但将MIME类型更改为application/vnd.openxmlformats-officedocument.presentationml.presentation后,在我的系统上下载该文件时会提示“无法打开文件”。当代码将文件写入服务器时,该文件是可以正常工作的。 - void
对我来说工作得非常完美。谢谢¡ - Jam

7

使用此调用

$objWriter->save('php://output');

要将XLS表格输出到当前页面,只需确保当前页面没有其他的echo、print或输出。

当使用共享主机时,在使用 $objWriter->save('php://output'); 时出现错误(可能与文件和文件夹权限有关)。第三方/PHPExcel/Writer/Excel2007.php:241 中的未捕获异常 'PHPExcel_Writer_Exception',消息为“无法打开php://output进行写入”。堆栈跟踪:#0 - Enrique
我正在尝试使用PHPPowerpoint构建PPT,按照提到的步骤进行操作,但将MIME类型更改为application/vnd.openxmlformats-officedocument.presentationml.presentation后,在我的系统上下载该文件时会提示“无法打开文件”。当代码将文件写入服务器时,该文件是可以正常工作的。 - void
将整个代码放在 ob_start(); 和 ob_end_clean(); 之间可以解决问题。 - Hussein mahyoub

6

使用XLSX文件格式

将文件名(包含扩展名)存储在$xlsName变量中。 例如:$xlsName = 'teste.xlsx';

$objPHPExcel = new PHPExcel();

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$xlsName.'"');
header('Cache-Control: max-age=0');
$objWriter->save('php://output');

针对XLS使用

$xlsName中设置带扩展名的XLS文件名。 示例: $xlsName ='teste.xls';

$objPHPExcel = new PHPExcel();

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$xlsName.'"');
header('Cache-Control: max-age=0');
$objWriter->save('php://output');

3
附:PSI.:XLS格式默认为“Excel5”,XLSX格式默认为“Excel2007”。 - Rogerio de Moraes
我正在尝试使用PHPPowerpoint构建PPT,按照提到的步骤进行操作,但将MIME类型更改为application/vnd.openxmlformats-officedocument.presentationml.presentation后,在我的系统上下载该文件时会提示“无法打开文件”。当代码将文件写入服务器时,该文件是可以正常工作的。 - void
xlsx 的内容类型应该为:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"。请参见 http://filext.com/faq/office_mime_types.php。 - kojow7

3

可能你已经解决了你的问题,不管怎样我希望这能帮到你。

下载的所有文件都以空行开始,在我的情况下是四个空行,并且会导致一些问题。无论你使用 readfile(); 还是 save('php://output');,可以通过在脚本开头添加 ob_start(); 并在 readfile() 或者 save('php://output'); 之前加上 ob_end_clean(); 来解决这个问题。


你遇到的问题与错误日志和报告有关:你没有看到警告,这些警告本应指向问题:头信息已经发送。这在这个参考问题中有详细说明:https://dev59.com/vmsz5IYBdhLWcg3wQFUq - hakre
2
ob_end_clean() 不是 od_end_clean()。 - turson

3
 header('Content-type: application/vnd.ms-excel');

 header('Content-Disposition: attachment; filename="file.xlsx"');

 header('Cache-Control: max-age=0');

 header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');

 header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');

 header ('Cache-Control: cache, must-revalidate');

 header ('Pragma: public');

 $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');

 $objWriter->save('php://output');

我正在尝试使用PHPPowerpoint构建PPT,按照所述步骤进行操作,但将"MIME"类型更改为"application/vnd.openxmlformats-officedocument.presentationml.presentation"后,在我的系统上下载文件时出现“无法打开文件”的错误。当代码将文件写入服务器时,文件是可以工作的。 - void

0

我尝试了大多数答案提出的$writer->save('php://output');命令。

但是下载的文件损坏了。

为了解决这个问题,我不得不这样做:

    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
    header('Content-type: application/vnd.ms-excel');
    header('Content-Disposition: attachment; filename="filename.xlsx"');
    header('Cache-Control: max-age=0');
    $path = 'path/to/temp/file.xlsx';
    // save content to temporary file
    $objWriter->save($path);
    // This header was key to me, in order to get it working
    header("Content-Length: ".filesize($path));
    // output file content
    readfile($path);
    // delete temporary file
    unlink($path);

0
重要的是要说明,对于使用Grocery CRUD v2.9 - v3的CodeIgniter用户来说,有时候你可能会发现导出的Excel文件损坏无法打开。
你可能需要实际修改处理导出到Excel的代码部分在GroceryCrud中(尽管不建议更改源代码)。特别是在ExportState.php中的exportToExcel()函数中,在下面突出显示的代码块之前和之后添加ob_end_clean():
// rest of code above....

        ob_end_clean();
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"');
        header('Cache-Control: max-age=0');

        // If you're serving to IE over SSL, then the following may be needed
        header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified
        header ('Cache-Control: cache, must-revalidate'); // HTTP/1.1
        header ('Pragma: public'); // HTTP/1.0
        ob_end_clean();

        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $objWriter->save('php://output');

obs_end_clean()将清除输出,从而不会干扰您真正要发送给浏览器的内容,可能会导致文件损坏的问题。

希望能在除了GroceryCrud之外的自己实现中有所帮助。技巧是在头部之前和之后添加obs_end_clean()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接