Asked  7 Months ago    Answers:  5   Viewed   35 times

By going through the Codeigniter documentation, I am using the following code to force download files from my server.

function download($file_id){
        $file = $this->uploadmodel->getById($file_id); //getting all the file details
                                                      //for $file_id (all details are stored in DB)
        $data = file_get_contents($file->full_path); // Read the file's contents
        $name = $file->file_name;;

        force_download($name, $data);
    }

The code is working file for images, but when it comes with the case of PDF files, it is not working. I have not tested it for all file extensions, but since it is not working for PDF, it might not work for other various file types. Any solution?

 Answers

80

I've had similar problems. I think the problem resides in certain mime's and headers sent to the browser(s). I've end up using the code I found here http://taggedzi.com/articles/display/forcing-downloads-through-codeigniter. Use the function below instead of force_download. It has worked for me so far.

    function _push_file($path, $name)
    {
      // make sure it's a file before doing anything!
      if(is_file($path))
      {
        // required for IE
        if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }

        // get the file mime type using the file extension
        $this->load->helper('file');

        $mime = get_mime_by_extension($path);

        // Build the headers to push out the file properly.
        header('Pragma: public');     // required
        header('Expires: 0');         // no cache
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($path)).' GMT');
        header('Cache-Control: private',false);
        header('Content-Type: '.$mime);  // Add the mime type from Code igniter.
        header('Content-Disposition: attachment; filename="'.basename($name).'"');  // Add the file name
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: '.filesize($path)); // provide file size
        header('Connection: close');
        readfile($path); // push it out
        exit();
    }
}

Hope it helps.

Wednesday, March 31, 2021
 
keyBeatz
answered 7 Months ago
44

I've used PHPExcel with CodeIgniter successfully before.

All I did was drop the phpexcel folder into application/third-party and created the following wrapper library:

<?php

class Excel {

    private $excel;

    public function __construct() {
        // initialise the reference to the codeigniter instance
        require_once APPPATH.'third_party/phpexcel/PHPExcel.php';
        $this->excel = new PHPExcel();    
    }

    public function load($path) {
        $objReader = PHPExcel_IOFactory::createReader('Excel5');
        $this->excel = $objReader->load($path);
    }

    public function save($path) {
        // Write out as the new file
        $objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel5');
        $objWriter->save($path);
    }

    public function stream($filename) {       
        header('Content-type: application/ms-excel');
        header("Content-Disposition: attachment; filename="".$filename."""); 
        header("Cache-control: private");        
        $objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel5');
        $objWriter->save('php://output');    
    }

    public function  __call($name, $arguments) {  
        // make sure our child object has this method  
        if(method_exists($this->excel, $name)) {  
            // forward the call to our child object  
            return call_user_func_array(array($this->excel, $name), $arguments);  
        }  
        return null;  
    }  
}

?>

I could then do the following in my controllers:

$this->load->library("excel");
$this->excel->load("/path/to/input.xls");
$this->excel->setActiveSheetIndex(0);
$this->excel->getActiveSheet()->SetCellValue('B2', "whatever");
$this->excel->save("/path/to/output.xls");

Hope this helps you out?

Wednesday, March 31, 2021
 
CBroe
answered 7 Months ago
56

Make sure you're not running any compression output buffering handlers, such as ob_gzhandler. I had a similar case and I had to disable output buffering for this to work properly

Saturday, May 29, 2021
 
tplaner
answered 5 Months ago
75

the problem is that the excel file is saved version 5, then I should Register with the 2007 version (. xlsx) and the Arabic values ??appear correctly in file properities:

$obj_writer = PHPExcel_IOFactory::createWriter($this->excel, 'Excel2007');
$obj_writer->save('php://output');
Saturday, May 29, 2021
 
BlueNile
answered 5 Months ago
46

THis is hard - most php configuration will fail after 30 seconds. If you own php.ini you can change that to longer limit. But still - is that even worth it? I mean - the files can get bigger or network slower - and once more you will hit the timeout.

This is why downloaders were made - to download big files in smaller chunks Half Crazed showed you code for that i THIS answer (its not only one - this only takes into account one of the ways clients negotiate the transfers - but still its a good start).

Mega.co.nz for example uses new html5 features. Downloads the file in browser using chunks, joining the file on user and and then ,,downloading'' it from the browser disk space. It can resume files, pause files and so on. (Sorry - no code for that as it would be quite big and include more than one language (php, js)).

PS: change yours readfile($path); into:

$handle=fopen($path, 'rb');
while (!feof($handle))
{
    echo fread($handle, 8192);
    flush();
}
fclose($handle);

This will not load WHOLE file into memory, just parts of 8KiB at once and then send them to user.

Tuesday, August 17, 2021
 
Sen
answered 2 Months ago
Sen
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :