can't save file use save('php://output')

Topics: Developer Forum, Project Management Forum, User Forum
Mar 10, 2009 at 8:39 AM
Edited Mar 10, 2009 at 8:40 AM
I use PHPExcel with CodeIgniter .
Look at the following code:
<?
        .............................
        header('Pragma: public');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-Type: application/force-download');
        header('Content-Type: application/octet-stream');
        header('Content-Type: application/download');
        header("Content-Disposition: attachment;filename={$filename}");
        header('Content-Transfer-Encoding: binary');

        // output the file
        $objWriter = PHPExcel_IOFactory::createWriter($this->excel->workbook,'Excel5');
        
        #$objWriter->save('test.xls');
        $objWriter->save('php://output');
        exit;
?>
when I use "$objWriter->save('test.xls');" the .xls file can save in the root document success.
but when I use "$objWriter->save('php://output');" I can only see the garbled.

Who can tell me why it happened ?????????????????
Developer
Mar 10, 2009 at 6:27 PM
If your test.xls file open fine, then the reason is most likely your HTTP headers.

1. By the way, we have updated the recommendation to use this for output by Excel5 writer:

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

2. The above is not likely to solve your problem. It could be your CodeIgniter that is altering the headers, but I'm not sure. Check your HTTP response headers by downloading the Live HTTP Headers add-on for Firefox.
https://addons.mozilla.org/en-US/firefox/addon/3829

See if there is something strange, like a different Content-Type than application/vnd.ms-excel

Mar 11, 2009 at 2:07 AM
My browser is IE Explorer 8.0.  Maybe it cause by the  encoding. because my windows encoding by GB2312 but the web page header encoding by UTF8.
Developer
Mar 11, 2009 at 7:19 PM
With the above code you are supposed to get a download dialog that prompts you to save or open the Excel file. Please provide us with a full dump of the HTTP response headers using the Live HTTP Headers add-on?

Apr 3, 2009 at 3:22 PM
Edited Apr 3, 2009 at 3:27 PM
I will gladly continue the thread.

We're experiencing the same problem (except we don't use CodeIgniter - just PHP on linux with Apache). When we save it to the filesystem (on Linux), the excel file opens (in Windows) without a problem. We've upgraded the code to version 1.6.6 in an attempt to get this resolved - without success. In PHP we are using:


$head_filename = "Content-Disposition: attachment;filename=\"" . $the_file_name . "\"";
header('Content-Type: application/vnd.ms-excel');
header($head_filename);
header('Cache-Control: max-age=0');


When the file is opened (with Notepad++), it contains three blank lines and the following:

bool(false)

Yet if I comment out the header lines and replace it with:

$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($the_file_name);


Then the file opens fine in Excel.

Using Live HTTP Headers, this is what happens when I click the link to generate the file:

http://---URL-REMOVED

GET /--PATH-URL-REMOVED HTTP/1.1
Host: --IP-REMOVED
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://---URL-REMOVED

HTTP/1.x 200 OK
Date: Fri, 03 Apr 2009 14:19:49 GMT
Server: Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.9
X-Powered-By: PHP/5.2.9
content-disposition: attachment;filename="BusinessValidation.xls"
Cache-Control: max-age=0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Length: 7695
Content-Type: application/vnd.ms-excel
----------------------------------------------------------


BTW: This is the last lines in my code - no php ending, no blank lines, just this:

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


Any ideas?

Thanks for your time!
Developer
Apr 3, 2009 at 3:51 PM
@gniknalu: This looks strange, I can't spot the error except that I'm wondering where bool(false) comes from. Your HTTP headers look ok. Does that mean you get the download dialog ok, but after you download the file it contains just some blank lines plus the text "bool(false)" ?

I would try to find out where that bool(false) comes from. It looks like you may have some var_dump() statement somewhere which should be removed? There must not be any echo statements or the like when you output Excel file for download.

Apr 3, 2009 at 4:31 PM
Sorry - the var_dump() was there during debugging. That took care of the bool(false) line. . .

The file, when the three blank lines and the bool(false) are removed, opens fine in excel and looks as expected.

Our script presents the user with a link that, when clicked, immediately presents the download dialog box (the HTTP headers you've reviewed). As a work-around, we've been saving the file to the local file system, emailing the file and then unlinking it.

The code that generates the excel file has been reviewed ad nauseam - no echo or print statements or anything else that would output.  In fact, after removing the var_dump line, I removed all comments and blank lines from the code to see if it had any impact - it had none. . . . . .
Developer
Apr 3, 2009 at 4:49 PM
Ok, I understand. I thought that the file contained nothing but the three blank lines + bool(false). I see this is not the case since you are saying that the Excel file is fine when the blank lines are deleted.

You need to find out where those blank lines are coming from. This kind usually comes from blank lines before the opening <?php or blank lines after the closing ?> in your script. Remove them and it will fix the problem.

It is also a good idea to omit the optional closing ?> whenever possible. At least you will then not have to worry about blank lines after the closing ?>.

Apr 3, 2009 at 10:39 PM
I'll keep looking.

As mentioned previously:

BTW: This is the last lines in my code - no php ending, no blank lines, just this:
$objWriter = PHPExcel_IOFactory :: createWriter($objPHPExcel, 'Excel5');
$objWriter->save('php://output');


Thanks for the fast responses!
Developer
Apr 3, 2009 at 10:55 PM
Keep looking. Remember to check all included files too. The way I usually do this is to put ob_start() at the very beginning of my script and then check the output buffer at various points to track at what point the blank lines are inserted. The following example shows the technique:

<?php
ob_start();

echo 'hello';
var_dump(ob_get_contents()); // string(5) "hello"
echo 'abc';
?>

Apr 6, 2009 at 3:00 PM
<?php
/** PHPExcel */
include 'PHPExcel.php';

/** PHPExcel_IOFactory */
include 'PHPExcel/IOFactory.php';

// Create new PHPExcel object
$objPHPExcel = new PHPExcel();


// Set properties
$objPHPExcel->getProperties()->setCreator("MIS");
$objPHPExcel->getProperties()->setLastModifiedBy("MIS");
$objPHPExcel->getProperties()->setTitle("MIS");
$objPHPExcel->getProperties()->setSubject("Attendance");
$objPHPExcel->getProperties()->setDescription("Information File");


// Add Data
$objPHPExcel->setActiveSheetIndex(0);
$objPHPExcel->getActiveSheet()->SetCellValue('A1', 'Academic Year');
$objPHPExcel->getActiveSheet()->SetCellValue('B1', 'Semester');
$objPHPExcel->getActiveSheet()->SetCellValue('C1', 'Faculty');
$objPHPExcel->getActiveSheet()->SetCellValue('D1', 'Department');
$objPHPExcel->getActiveSheet()->SetCellValue('E1', 'Course');
$objPHPExcel->getActiveSheet()->SetCellValue('F1', 'Register no.');
$objPHPExcel->getActiveSheet()->SetCellValue('G1', 'Name');
$objPHPExcel->getActiveSheet()->SetCellValue('H1', 'Attendance Percentage');


$objPHPExcel->getActiveSheet()->setTitle('Attendance');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');

header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header("Content-Disposition: attachment;filename=attendance.xlsx");
header('Content-Transfer-Encoding: binary');

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



I want to use force downloading when client browses this page. When I use this code it is working fine only in "Microsoft Windows" runing PC's client browsers. When I try in Linux OS running PC as Client machine it is not working. How can I solve this problem? (Note that my Server OS is Linux).
Apr 7, 2009 at 3:34 PM
A code review fixed my problems. One of the scripts calls a script (that calls a script - you know the routine). That script (and it's friends) had three extra lines after the closing tag. So I'm good!
Developer
Apr 8, 2009 at 9:53 AM
@samudaya: Can you instead try to use the headers as shown in the latest documentation? What is happening on your Linux OS client machine, you don't get a download dialog?