Reputation: 2139
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
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
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
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
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
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
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