Ticket #610: download.php

File download.php, 2.7 kB (added by SuicidalWeasel, 5 months ago)

Modified download helper to handle larger file sizes

Line 
1<?php defined('SYSPATH') or die('No direct script access.');
2/**
3 * Download helper class.
4 *
5 * $Id$
6 *
7 * @package    Core
8 * @author     Kohana Team
9 * @copyright  (c) 2007-2008 Kohana Team
10 * @license    http://kohanaphp.com/license.html
11 */
12class download_Core {
13
14    /**
15     * Force a download of a file to the user's browser. This function is
16     * binary-safe and will work with any MIME type that Kohana is aware of.
17     *
18     * @param   string  a file path or file name
19     * @param   mixed   data to be sent if the filename does not exist
20     * @param   float      size of block to be read from file at a time in megabytes
21     * @return  void
22     */
23    public static function force($filename = '', $data = '', $blocksize = 1)
24    {
25        static $user_agent;
26
27        if ($filename == '')
28            return FALSE;
29       
30        if (valid::numeric($blocksize))
31            $blocksize = abs($blocksize);
32        else
33            return FALSE;
34
35        if (is_file($filename))
36        {
37            // Get the real path
38            $filepath = str_replace('\\', '/', realpath($filename));
39
40            // Get extension
41            $extension = pathinfo($filepath, PATHINFO_EXTENSION);
42
43            // Remove directory path from the filename
44            $filename = end(explode('/', $filepath));
45
46            // Set filesize
47            $filesize = filesize($filepath);
48        }
49        else
50        {
51            // Grab the file extension
52            $extension = end(explode('.', $filename));
53
54            // Try to determine if the filename includes a file extension.
55            // We need it in order to set the MIME type
56            if (empty($data) OR $extension === $filename)
57                return FALSE;
58
59            // Set filesize
60            $filesize = strlen($data);
61        }
62
63        // Set a default mime if we can't find it
64        if (($mime = Config::item('mimes.'.$extension)) === NULL)
65        {
66            $mime = 'application/octet-stream';
67        }
68        else
69        {
70            $mime = current((array) $mime);
71        }
72
73        // Generate the server headers
74        header('Content-Type: '.$mime);
75        header('Content-Disposition: attachment; filename="'.$filename.'"');
76        header('Content-Transfer-Encoding: binary');
77        header('Expires: 0');
78        header('Content-Length: '.$filesize);
79       
80        // IE headers
81        if (Kohana::user_agent('browser') === 'Internet Explorer')
82        {
83            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
84            header('Pragma: public');
85        }
86        else
87        {
88            header('Pragma: no-cache');
89        }
90
91        if (isset($filepath))
92        {
93            // Convert blocksize to bytes
94            $blocksize *= 1000000;
95           
96            // Open the file
97            $handle = fopen($filepath, 'rb');
98           
99            // Loop through the file, 1MB at a time
100            while ( ! feof($handle))
101            {
102                // Echo the result
103                echo fread($handle, $blocksize);
104               
105                // Flush the output buffer to start sending data
106                ob_flush();
107                flush();
108            }
109           
110            // Close the file
111            fclose($handle);
112        }
113        else
114        {
115            // Send the file data
116            echo $data;
117        }
118    }
119
120} // End download