Ejemplo n.º 1
0
 /**
  * Provides the ability to download a file to the browser
  *
  * @param string $file the full path to the file to be downloaded
  * @param bool $force_download as opposed to letting browser choose if to download or render
  * @param int $sec      Throttling, try 0.1 for some speed throttling of downloads
  * @param int $bytes    Size of chunks to send in bytes. Default is 1024
  * @throws \Exception
  */
 public static function download($file, $force_download = true, $sec = 0, $bytes = 1024)
 {
     if (file_exists($file)) {
         // fire download event
         Grav::instance()->fireEvent('onBeforeDownload', new Event(['file' => $file]));
         $file_parts = pathinfo($file);
         $mimetype = Utils::getMimeType($file_parts['extension']);
         $size = filesize($file);
         // File size
         // clean all buffers
         while (ob_get_level()) {
             ob_end_clean();
         }
         // required for IE, otherwise Content-Disposition may be ignored
         if (ini_get('zlib.output_compression')) {
             ini_set('zlib.output_compression', 'Off');
         }
         header("Content-Type: " . $mimetype);
         header('Accept-Ranges: bytes');
         if ($force_download) {
             // output the regular HTTP headers
             header('Content-Disposition: attachment; filename="' . $file_parts['basename'] . '"');
         }
         // multipart-download and download resuming support
         if (isset($_SERVER['HTTP_RANGE'])) {
             list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
             list($range) = explode(",", $range, 2);
             list($range, $range_end) = explode("-", $range);
             $range = intval($range);
             if (!$range_end) {
                 $range_end = $size - 1;
             } else {
                 $range_end = intval($range_end);
             }
             $new_length = $range_end - $range + 1;
             header("HTTP/1.1 206 Partial Content");
             header("Content-Length: {$new_length}");
             header("Content-Range: bytes {$range}-{$range_end}/{$size}");
         } else {
             $new_length = $size;
             header("Content-Length: " . $size);
             if (Grav::instance()['config']->get('system.cache.enabled')) {
                 $expires = Grav::instance()['config']->get('system.pages.expires');
                 if ($expires > 0) {
                     $expires_date = gmdate('D, d M Y H:i:s T', time() + $expires);
                     header('Cache-Control: max-age=' . $expires);
                     header('Expires: ' . $expires_date);
                     header('Pragma: cache');
                 }
                 header('Last-Modified: ' . gmdate("D, d M Y H:i:s T", filemtime($file)));
                 // Return 304 Not Modified if the file is already cached in the browser
                 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($file)) {
                     header('HTTP/1.1 304 Not Modified');
                     exit;
                 }
             }
         }
         /* output the file itself */
         $chunksize = $bytes * 8;
         //you may want to change this
         $bytes_send = 0;
         $fp = @fopen($file, 'r');
         if ($fp) {
             if (isset($_SERVER['HTTP_RANGE'])) {
                 fseek($fp, $range);
             }
             while (!feof($fp) && !connection_aborted() && $bytes_send < $new_length) {
                 $buffer = fread($fp, $chunksize);
                 echo $buffer;
                 //echo($buffer); // is also possible
                 flush();
                 usleep($sec * 1000000);
                 $bytes_send += strlen($buffer);
             }
             fclose($fp);
         } else {
             throw new \Exception('Error - can not open file.');
         }
         exit;
     }
 }
Ejemplo n.º 2
0
 /**
  * Provides the ability to download a file to the browser
  *
  * @param      $file            the full path to the file to be downloaded
  * @param bool $force_download  as opposed to letting browser choose if to download or render
  */
 public static function download($file, $force_download = true)
 {
     if (file_exists($file)) {
         // fire download event
         self::getGrav()->fireEvent('onBeforeDownload', new Event(['file' => $file]));
         $file_parts = pathinfo($file);
         $filesize = filesize($file);
         // check if this function is available, if so use it to stop any timeouts
         if (function_exists('set_time_limit')) {
             set_time_limit(0);
         }
         ignore_user_abort(false);
         if ($force_download) {
             header('Content-Description: File Transfer');
             header('Content-Type: application/octet-stream');
             header('Content-Disposition: attachment; filename=' . $file_parts['basename']);
             header('Content-Transfer-Encoding: binary');
             header('Expires: 0');
             header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
             header('Pragma: public');
         } else {
             header("Content-Type: " . Utils::getMimeType($file_parts['extension']));
         }
         header('Content-Length: ' . $filesize);
         // 8kb chunks for now
         $chunk = 8 * 1024;
         $fh = fopen($file, "rb");
         if ($fh === false) {
             return;
         }
         // Repeat reading until EOF
         while (!feof($fh)) {
             echo fread($fh, $chunk);
             ob_flush();
             // flush output
             flush();
         }
         exit;
     }
 }
Ejemplo n.º 3
0
 public function testGetMimeType()
 {
     $this->assertEquals(Utils::getMimeType(''), 'application/octet-stream');
     $this->assertEquals(Utils::getMimeType('jpg'), 'image/jpeg');
     $this->assertEquals(Utils::getMimeType('png'), 'image/png');
     $this->assertEquals(Utils::getMimeType('txt'), 'text/plain');
     $this->assertEquals(Utils::getMimeType('doc'), 'application/msword');
 }