/** * Send data from a file based on the current Range header * * @param string $path Local file system path to serve * @param string $contentType MIME type of the data stream */ public function sendFile($path, $contentType = 'application/octet-stream') { // Make sure the file exists and is a file, otherwise we are wasting our time $localPath = realpath($path); if ($localPath === false || !is_file($localPath)) { throw new UpdraftPlus_NonExistentFileException($path . ' does not exist or is not a file'); } // Make sure we can open the file for reading if (!($fp = fopen($localPath, 'r'))) { throw new UpdraftPlus_UnreadableFileException('Failed to open ' . $localPath . ' for reading'); } $fileSize = filesize($localPath); if ($this->range == null) { // No range requested, just send the whole file header('HTTP/1.1 200 OK'); $this->sendDownloadHeaders(basename($localPath), $fileSize, $contentType); fpassthru($fp); } else { // Send the request range header('HTTP/1.1 206 Partial Content'); header('Content-Range: ' . $this->range->getContentRangeHeader($fileSize)); $this->sendDownloadHeaders(basename($localPath), $this->range->getLength($fileSize), $contentType); $this->sendDataRange($fp, $this->range->getStartPosition($fileSize), $this->range->getLength($fileSize)); } fclose($fp); }
public function spool_file($fullpath, $encryption = '') { @set_time_limit(900); if (file_exists($fullpath)) { // Prevent any debug output // Don't enable this line - it causes 500 HTTP errors in some cases/hosts on some large files, for unknown reason //@ini_set('display_errors', '0'); $spooled = false; if ('.crypt' == substr($fullpath, -6, 6)) { if (ob_get_level()) { $flush_max = min(5, (int) ob_get_level()); for ($i = 1; $i <= $flush_max; $i++) { @ob_end_clean(); } } header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past $this->spool_crypted_file($fullpath, (string) $encryption); return; } $content_type = $this->get_mime_type_from_filename($fullpath, false); require_once UPDRAFTPLUS_DIR . '/includes/class-partialfileservlet.php'; //Prevent the file being read into memory if (ob_get_level()) { $flush_max = min(5, (int) ob_get_level()); for ($i = 1; $i <= $flush_max; $i++) { @ob_end_clean(); } } if (ob_get_level()) { @ob_end_clean(); } // Twice - see HS#6673 - someone at least needed it if (isset($_SERVER['HTTP_RANGE'])) { $range_header = trim($_SERVER['HTTP_RANGE']); } elseif (function_exists('apache_request_headers')) { foreach (apache_request_headers() as $name => $value) { if (strtoupper($name) === 'RANGE') { $range_header = trim($value); } } } if (empty($range_header)) { header("Content-Length: " . filesize($fullpath)); header("Content-type: {$content_type}"); header("Content-Disposition: attachment; filename=\"" . basename($fullpath) . "\";"); readfile($fullpath); return; } try { $range_header = UpdraftPlus_RangeHeader::createFromHeaderString($range_header); $servlet = new UpdraftPlus_PartialFileServlet($range_header); $servlet->sendFile($fullpath, $content_type); } catch (UpdraftPlus_InvalidRangeHeaderException $e) { header("HTTP/1.1 400 Bad Request"); error_log("UpdraftPlus: UpdraftPlus_InvalidRangeHeaderException: " . $e->getMessage()); } catch (UpdraftPlus_UnsatisfiableRangeException $e) { header("HTTP/1.1 416 Range Not Satisfiable"); } catch (UpdraftPlus_NonExistentFileException $e) { header("HTTP/1.1 404 Not Found"); } catch (UpdraftPlus_UnreadableFileException $e) { header("HTTP/1.1 500 Internal Server Error"); } } else { echo __('File not found', 'updraftplus'); } }