DoubleClickOnThis
DoubleClickOnThis

Reputation: 101

(PHP) Save file in folder to computer

I'm using PHP (PHPExcel) to handle all the excel files. Currently I have saved a "New Template.xlsx" in a folder. And now I want the users to be able to download the "New Template.xlsx" at a click of a button.

How do i do that with php or phpexcel (i'm using Yii PHP framework as well)?

I'm not sure how to start, all I have now is

   $filePath = Yii::app()->basePath . '\\vendors\\Excel Template\\New Template.xlsx';
    Yii::import('application.vendors.PHPExcel', true);
    $objPHPExcel = PHPExcel_IOFactory::load($filePath);
    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');

Edit

Thanks to Miqi180's comments, I'm now able to download the excel file, however I am unable to open it because of invalid file extension/file format.

Here are my codes:

<?php

ignore_user_abort(true);
set_time_limit(0); // disable the time limit for this script

//$path = "/absolute_path_to_your_files/"; // change the path to fit your websites document structure
$path = Yii::app()->basePath . '\\vendors\\Excel Template\\';
//$dl_file = preg_replace("([^\w\s\d\-_~,;:\[\]\(\].]|[\.]{2,})", '', $_GET['download_file']); // simple file name validation
$dl_file = preg_replace("([^\w\s\d\-_~,;:\[\]\(\].]|[\.]{2,})", '', 'NewTemplate.xlsx'); // simple file name validation
$dl_file = filter_var($dl_file, FILTER_SANITIZE_URL); // Remove (more) invalid characters
$fullPath = $path.$dl_file;

if ($fd = fopen ($fullPath, "r")) {
    $fsize = filesize($fullPath);
    $path_parts = pathinfo($fullPath);
    $ext = strtolower($path_parts["extension"]);
    switch ($ext) {
        case "xlsx":
        //header("Content-type: application/vnd.ms-excel");
        header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a file download
        break;
        // add more headers for other content types here
        default;
        header("Content-type: application/octet-stream");
        header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
        break;
    }
    header("Content-length: $fsize");
    header("Cache-control: private"); //use this to open files directly
    while(!feof($fd)) {
        $buffer = fread($fd, 2048);
        echo $buffer;
    }
}
fclose ($fd);
exit;

Upvotes: 1

Views: 2100

Answers (2)

Miqi180
Miqi180

Reputation: 1691

Basically, what you need to do is execute a php script which fires when another page is loaded, e.g. "download.php" and then send the file through the header commands in that script.

Complete working code example taken from here:

<?php

ignore_user_abort(true);
set_time_limit(0); // disable the time limit for this script

$path = "/absolute_path_to_your_files/"; // change the path to fit your websites document structure
$dl_file = preg_replace("([^\w\s\d\-_~,;:\[\]\(\].]|[\.]{2,})", '', $_GET['download_file']); // simple file name validation
$dl_file = filter_var($dl_file, FILTER_SANITIZE_URL); // Remove (more) invalid characters
$fullPath = $path.$dl_file;

if ($fd = fopen ($fullPath, "r")) {
    $fsize = filesize($fullPath);
    $path_parts = pathinfo($fullPath);
    $ext = strtolower($path_parts["extension"]);
    switch ($ext) {
        case "pdf":
        header("Content-type: application/pdf");
        header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a file download
        break;
        // add more headers for other content types here
        default;
        header("Content-type: application/octet-stream");
        header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
        break;
    }
    header("Content-length: $fsize");
    header("Cache-control: private"); //use this to open files directly
    while(!feof($fd)) {
        $buffer = fread($fd, 2048);
        echo $buffer;
    }
}
fclose ($fd);
exit;

However, you need to set the content-type correctly first (see this post).

from

header("Content-type: application/pdf");

to

header("Content-type: application/vnd.ms-excel");

or for For Excel2007 and above .xlsx files

header("Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

Edit:

According to this MSDN blog article, the correct Extension MIME type for Excel .xlsx files actually is:

application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

Upvotes: 1

Mark Baker
Mark Baker

Reputation: 212412

  • Stop Yii from sending its own headers and output
  • Send the appropriate headers for an xlsx file
  • Save the file to php://output

Look at some of the examples in the PHPExcel Examples folder like 01simple-download-xlsx.php

But unless you're changing the template between loading it and sending it to the user, there's no need to use PHPExcel for this

Upvotes: 1

Related Questions