Sainath Krishnan
Sainath Krishnan

Reputation: 2139

PHPExcel download not working properly

I am trying to create a page that allows a user to download the contents of an SQL table, into an excel file.

Problem : When I open the excel file, it only contains random gibberish. An example -

PKQ=DG’D²Xð[Content_Types].xml­”MNÃ0…÷œ"ò%nY „švAa
•(0ö¤±êØ–gúw{&i‰@ÕnbEö{ßøyìÑdÛ¸l
mð¥‘×ÁX¿(ÅÛü)¿’òF¹à¡;@1_滘±Øc)j¢x/%ê…Eˆày¦

This is my code -

<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

$download="";
if (isset($_GET['surveyid'])) {
//Survey ID
$download = $_GET['surveyid'];
require_once('../Classes/PHPExcel.php');

$query="SELECT b.question_id as qid,
                a.question as ques,
                b.response as response,
                count(b.response) as cnt
          FROM v3_sai.survey_responses b 
          INNER JOIN v3_sai.survey_questions a 
             ON a.id = b.question_id 
                AND a.survey_id=".intval($download)."
          group by b.response, a.question
          order by b.question_id";
          var_dump($query);
$resultdl= mysql_query($query) or die(mysql_error());
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$rowcount=1;
while($row = mysql_fetch_array($resultdl)){
$objPHPExcel->getActiveSheet()->SetCellValue('A'.$rowcount, $row['qid']);
$objPHPExcel->getActiveSheet()->SetCellValue('B'.$rowcount, $row['ques']); 
$objPHPExcel->getActiveSheet()->SetCellValue('C'.$rowcount, $row['response']);
$objPHPExcel->getActiveSheet()->SetCellValue('D'.$rowcount, $row['cnt']); 
$rowCount++; 
} 
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); 
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="file.xls"');
$objWriter->save('php://output');
die();
}

Upvotes: 2

Views: 18452

Answers (6)

Gamelot
Gamelot

Reputation: 11

For me, line header("Content-Type:application/vnd.ms-excel"); helped.

    $uri = 'public://export/' . $filename;

    $writer = (in_array($active_sheet, [30])) ? IOFactory::createWriter($spreadsheet, "Xlsx") : IOFactory::createWriter($spreadsheet, "Xls");

    $writer->save($uri);

    if (\Drupal::service('stream_wrapper_manager')->isValidScheme('public') && file_exists($uri)) {
      header("Content-Type:application/vnd.ms-excel");
      $response = new BinaryFileResponse($uri);
      $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename);
      $form_state->setResponse($response);
    }

Upvotes: 0

Julius Moshiro
Julius Moshiro

Reputation: 730

I know i might be responding a bit late to this but none of the above worked for me. It's true using ob_clean(); will remove any cached material so that it does not interfere with the returned headers + file content. What matters is where do you clean of the extra gibberish. So after days of scratching my head i've noticed that you need to ob_clean(); right before the headers. If you do it somewhere else you will have the same problem. Here is a sample code that worked for me.

            ob_clean();
            $fileName = "Test.xlsx";
            # Output headers.
            header("Set-Cookie: fileDownload=true; path=/");
            header("Cache-Control: private");
            header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            header("Content-Disposition: attachment; filename='".$fileName."'");
            // If you're serving to IE 9, then the following may be needed
            header('Cache-Control: max-age=1');
            // 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
            # Output file.
            $return->save('php://output');
            die();

Upvotes: 2

castle
castle

Reputation: 83

I met with the same problem and finally found what was causing it. Somewhere before $objWriter->save('php://output') is called the output buffer is being written to unintentionally. You can test this by var_dump(ob_get_contents()) just before $objWriter->save('php://output').

A quick fix would be to add ob_​start() at the beginning of the script and then ob_​end_​clean() just before $objWriter->save('php://output')but the perfect fix would be to find where the output buffer is being filled in.

Upvotes: 0

Agha Umair Ahmed
Agha Umair Ahmed

Reputation: 1020

You can use like this

<?php 
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=abc".xls");
header("Pragma: no-cache");
header ("Expires: 0");
?>
    <table width="100%" border="1">
        <tr>
            <td>
                <h1> qid</h1>
            </td>
            <td>
                <h1> ques</h1>
            </td>
            <td>
                <h1> response</h1>
            </td>
            <td>
                <h1> cnt</h1>
            </td>
        </tr>

    while($row = mysql_fetch_array($resultdl)){
        <tr>
            <td>
                <?php echo $row['qid']; ?>
            </td>
            <td>
                <?php echo $row['ques']; ?>
            </td>
            <td>
                <?php echo $row['response']; ?>
            </td>
            <td>
                <?php echo $row['cnt']; ?>
            </td>
        </tr>

    <?php } ?>

    </table>

Upvotes: -5

Mark Baker
Mark Baker

Reputation: 212412

If youre downloading an xls file (BIFF), use the PHPExcel_Writer_Excel5 Writer; if you're downloading an .xlsx file (OfficeOpenXML), use the PHPExcel_Writer_Excel2007 Writer: DON'T mix and match... that's your problem. You're creating an .xlsx (OfficeOpenXML) file using the Excel2007 Writer, but setting the headers to tell the browser to expect an .xls (BIFF) file

Recommended headers for an .xls (BIFF) download are:

// Redirect output to a client’s web browser (Excel5)
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="01simple.xls"');
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
header('Cache-Control: max-age=1');

// 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

Recommended headers for an .xlsx (OfficeOpenXML) download are:

// Redirect output to a client’s web browser (Excel2007)
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="01simple.xlsx"');
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
header('Cache-Control: max-age=1');

// 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

Note that Content-Type, Content-Disposition, may be treated as case-sensitive by browsers, so Content-Type is not the same as Content-type.... and I believe that may also give you problems

Upvotes: 3

Pankaj Dadure
Pankaj Dadure

Reputation: 677

Try this and disable error reporting.

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=file.xls");
header("Content-Transfer-Encoding: binary ");
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); 
$objWriter->setOffice2003Compatibility(true);
$objWriter->save('php://output');

Upvotes: 0

Related Questions