1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Helper; 4 5 use PhpOffice\PhpSpreadsheet\Exception; 6 7 class Downloader 8 { 9 protected string $filepath; 10 11 protected string $filename; 12 13 protected string $filetype; 14 15 protected const CONTENT_TYPES = [ 16 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 17 'xls' => 'application/vnd.ms-excel', 18 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 19 'csv' => 'text/csv', 20 'html' => 'text/html', 21 'pdf' => 'application/pdf', 22 ]; 23 24 public function __construct(string $folder, string $filename, ?string $filetype = null) 25 { 26 if ((is_dir($folder) === false) || (is_readable($folder) === false)) { 27 throw new Exception("Folder {$folder} is not accessable"); 28 } 29 $filepath = "{$folder}/{$filename}"; 30 $this->filepath = (string) realpath($filepath); 31 $this->filename = basename($filepath); 32 if ((file_exists($this->filepath) === false) || (is_readable($this->filepath) === false)) { 33 throw new Exception("{$this->filename} not found, or cannot be read"); 34 } 35 36 $filetype ??= pathinfo($filename, PATHINFO_EXTENSION); 37 if (array_key_exists(strtolower($filetype), self::CONTENT_TYPES) === false) { 38 throw new Exception("Invalid filetype: {$filetype} cannot be downloaded"); 39 } 40 $this->filetype = strtolower($filetype); 41 } 42 43 public function download(): void 44 { 45 $this->headers(); 46 47 readfile($this->filepath); 48 } 49 50 public function headers(): void 51 { 52 ob_clean(); 53 54 $this->contentType(); 55 $this->contentDisposition(); 56 $this->cacheHeaders(); 57 $this->fileSize(); 58 59 flush(); 60 } 61 62 protected function contentType(): void 63 { 64 header('Content-Type: ' . self::CONTENT_TYPES[$this->filetype]); 65 } 66 67 protected function contentDisposition(): void 68 { 69 header('Content-Disposition: attachment;filename="' . $this->filename . '"'); 70 } 71 72 protected function cacheHeaders(): void 73 { 74 header('Cache-Control: max-age=0'); 75 // If you're serving to IE 9, then the following may be needed 76 header('Cache-Control: max-age=1'); 77 78 // If you're serving to IE over SSL, then the following may be needed 79 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past 80 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified 81 header('Cache-Control: cache, must-revalidate'); // HTTP/1.1 82 header('Pragma: public'); // HTTP/1.0 83 } 84 85 protected function fileSize(): void 86 { 87 header('Content-Length: ' . filesize($this->filepath)); 88 } 89 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body