10

I have generated xmlx file and I am able to save it and provide it for the user via:

$writer->save('hello world.xlsx');
header('Location: hello world.xlsx');

However, then the file remains on the hard drive. I need to get rid of it as it is a security threat.

I tried unlinking the file

unlink('hello world.xlsx');

but that deletes the file too early so the user doesn't have access to it. If it can work with unlink then I need to be sure the file will be deleted (so proper using of die(); and such)

EDIT: It is not only for security reasons anymore. The provider doesn't allow saving files so it is the only way to go.

Brambor
  • 604
  • 1
  • 8
  • 25

4 Answers4

20

Use php://output

header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="file.xls"');
$writer->save("php://output");
Artyom Sokolov
  • 2,385
  • 3
  • 23
  • 34
  • 1
    That doesn't work as it returns what would be on the page rather that what would be in the file. So it is returning random warning instead of the file. – Brambor May 13 '18 at 20:34
  • @Brambor what is the warning there? – Artyom Sokolov May 13 '18 at 20:39
  • It is unrelated, it was there before when it worked, `Warning: date() expects parameter 2 to be integer, float given in "my_file_path"\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\Xlsx\DocProps.php on line 148` – Brambor May 13 '18 at 20:47
  • It essentialy offers a file to save. That file is a xls file that has this warning in `A2` So it is what would be on the page. – Brambor May 13 '18 at 20:48
  • @Brambor I would suggest to get rid of warnings first (i.e., to fix them) and then to try to generate file again. – Artyom Sokolov May 13 '18 at 20:58
  • But it is unrelated! I can generate the file, save it perfectly, by provided code and then header to it! – Brambor May 13 '18 at 22:54
  • When I do not use saved file as xmlx template then the warning disapears and the file is compleatly empty. So it was unrelated, I god rid of the warning. – Brambor May 13 '18 at 23:07
  • 1
    You were right afer all. Once all warnings were supressed the file showed just fine. The typical "you have to not echo anything if you wat to use header" error mistake. – Brambor May 13 '18 at 23:50
  • 2
    Add `exit();` at the end so it does not download rest of the page – Shahlin Ibrahim Mar 26 '20 at 08:15
  • I am getting cors error in laravel 7.34, when using these settings. Maybe you could help me, thank you very much. – JG_GJ May 24 '21 at 22:42
  • @JG_GJ Consider opening new question with detailed description of your setup, please and tag me here. – Artyom Sokolov May 25 '21 at 08:54
3

You could send the file directly after its creation, instead of the redirect to the file.

$filename = 'hello world.xlsx';
$writer->save($filename);

// Set the content-type:
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: ' . filesize($filename));
readfile($filename); // send file
unlink($filename); // delete file
exit;
Syscall
  • 19,327
  • 10
  • 37
  • 52
2

You can use an in memory file pointer and read back from it.

$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');

$fp = fopen("php://memory", "rw");
$writer->save($fp);
rewind($fp);

$contents = "";
while (!feof($fp)) {
    $contents .= fread($fp, 8000);
}
Rob Ryan
  • 153
  • 1
  • 1
  • 7
1

call ob_end_clean(); just before the $writer->save('php://output').

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

Zaheer Babar
  • 1,636
  • 1
  • 15
  • 17