Slim Framework & PHPExcel, let Slim download generated excel document


Hi all,

For a application i’m creating with AngularJS and Slim Framework I need the possibility to create excel files and automaticly download it.

To be able to create Excel docs, i’m using PHPExcel. But I can’t figure out how to download the created file directly from my server.

try {
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $this->msg = 'Success!';
        $this->statuscode = 200;
    } catch (Exception $e) {
        $this->msg = "Export failed!";
        $this->statuscode = 500;

This outputs in my browser binary code, but doesn’t download the file. Hope someone can help me.


@svanbelleghem, I’ve never used PHPExcel before, but this has worked for me in the past:

$document = "First, Last\n";
$document .= "Jimmy,Page\n";

header('Content-Type: text/xls');
header('Content-Disposition: attachment; filename="myfile.xls"'); 
echo $document;


Thanks for the reply!

But this has the sme result as previously described, all this does is output the text to my browser. What I need is to download desired file.


Hmmm…When I run that code in my browser it downloads a file titled ‘myfile.xsl’.


Try out this:

header(‘Content-Description: File Transfer’);
header(‘Content-Type: application/octet-stream’);
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/download”);
header(‘Content-Disposition: attachment; filename=“myfile.xls”’);
header(“Content-Transfer-Encoding: binary”);
//header('Content-Length: ’ . filesize($f)); /* perhaps also provide content length */


Thank you for the response!

Made some changed in my code but still doesn’t download the file.




   $res = $response->withHeader('Content-Description', 'File Transfer')
                ->withHeader('Content-Type', 'application/force-download')
                ->withHeader('Content-Type', 'application/download')
                ->withHeader('Content-Disposition', 'attachment;filename="'.basename($file).'"')
                ->withHeader('Expires', '0')
                ->withHeader('Cache-Control', 'must-revalidate')
                ->withHeader('Pragma', 'public')
                ->withHeader('Content-Length', filesize($file));

            return $res;


I created a page that downloads a .csv file recently.

I have a html file that takes in 2 dates that will do a post using slim. The php code will then create a .csv file and populate it based on the data returned form a mysqli query. I have tested this in chrome, firefox, and safari.


   $app->post('/api/dateRangeReport',function ($request, $response, $args) {
	$jsonArgs = $request->getParsedBody();
	header('Content-type: text/csv');
	$name = $jsonArgs['startDate']." through ".$jsonArgs['endDate'].".csv";
	header('Content-Disposition: attachment; filename="'.$name.'"'); 

	// do not cache the file
	header('Pragma: no-cache');
	header('Expires: 0');

	// create a file pointer connected to the output stream
	$file = fopen('php://output', 'w');

	// send the column headers
	fputcsv($file, array('tracking_number', 'store', 'street', 'state', 'zip', 'city', 'country', 'date', 'serial_number'));
	global $fawkesEngine;
	$results = $fawkesEngine->createDateRangeReport($jsonArgs);
	$data = array();
	// need to do some special formatting to prevent scientific notation
	foreach ($results as $value) {
		$formattedTrackingNumber = $value['tracking_number'];
		$formattedTrackingNumber = "=".'"'.$formattedTrackingNumber.'"';
		$formattedSerialNumber = $value['serial_number'];
		$formattedSerialNumber = "=".'"'.$formattedSerialNumber.'"';
		$dataTemp = array($formattedTrackingNumber,$value['store'],$value['street'],$value['state'],$value['zip'],$value['city']
			array_push($data, $dataTemp);

	// output each row of the data
	foreach ($data as $row)
		fputcsv($file, $row);


I have the exact same issue. Did you manage to fix it?



Maybe try this example to send a CSV file to the browser as download:

public function downloadCsv(Request $request, Response $response): ResponseInterface
	$response = $response->withHeader('Content-Type', 'text/csv');
	$response = $response->withHeader('Content-Disposition', 'attachment; filename="file.csv"');

    $stream = fopen('php://memory', 'r+');
    fwrite($stream, file_get_contents(__DIR__ . '/file.csv'));

    return $response->withBody(new \Slim\Http\Stream($stream));

To send a Excel (XLSX) file, you just need a different content-type:

public function downloadExcel(Request $request, Response $response): ResponseInterface
    $excel = new PHPExcel();

    $sheet = $excel->setActiveSheetIndex(0);
    $cell = $sheet->getCell('A1');

    $excelWriter = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');

    $excelFileName = __DIR__ . '/file.xlsx';

    // For Excel2007 and above .xlsx files   
    $response = $response->withHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
	$response = $response->withHeader('Content-Disposition', 'attachment; filename="file.xlsx"');

    $stream = fopen('php://memory', 'r+');
    fwrite($stream, file_get_contents($excelFileName););

    return $response->withBody(new \Slim\Http\Stream($stream));