<? /*********************************/ /* Copyright (c) Igor Nikolaev */ /*********************************/ if (!defined("DOWNLOADER_CLASS_PHP")) { define("DOWNLOADER_CLASS_PHP",1); define("kb", 1024); define("mb", 1024 * kb); define("mb10", 10 * mb); // // Класс для обеспечения скачивания файла скриптом PHP с поддержкой многопоточности // // Пример использования: // // $downloader = new Downloader("путь-к-файлу-с-именем-файла"); // $downloader->setName("имя файла, под которым он будет скачиваться"); // $downloader->download(); // // Можно использовать для трансляции медиа-файла по сети: // // $downloader = new Downloader("video.avi"); // $downloader->setContentType("video/x-msvideo"); // $downloader->download(); // class Downloader { var $log; var $filepath; var $blocksize = mb10; var $name = null; var $contentType = null; function Downloader($filepath) { global $_SERVER; $this->filepath = $filepath; } function download() { global $_SERVER; if (!file_exists($this->filepath)) { $this->header("HTTP/1.1 404 Not Found"); return; } $fh = fopen($this->filepath, "rb"); if (!$fh) { $this->header("HTTP/1.1 500 Internal Server Error"); return; } $requestRange = $this->getRequestRange(); fseek($fh, $requestRange->rangeStart, SEEK_SET); $readLength = $requestRange->rangeLength; if (!is_null($this->getName())) { $this->header("Content-Disposition: attachment; filename=\"".$this->getName()."\""); } if ($requestRange->isPartial) { $this->header("HTTP/1.1 206 Partial content"); $this->header("Content-Range: bytes ".$requestRange->rangeStart."-".$requestRange->rangeEnd."/".$requestRange->fileLength); } $this->header("Accept-Ranges: bytes"); $this->header("ETag: ".$this->getETag()); $this->header("Content-Length: ".$requestRange->rangeLength); $this->header("Content-Type: ".$this->getContentType()); $this->header("Content-Transfer-Encoding: binary"); $this->header("Last-Modified: ".$this->getLastModified()); while ($readLength > 0) { $readsize = $this->blocksize; if ($readLength < $this->blocksize) $readsize = $readLength; $data = fread($fh, $readsize); $readLength -= $readsize; echo $data; } fclose($fh); } function setName($name) { global $_SERVER; $this->name = $name; if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { $this->name = preg_replace('/\./', '%2e', $this->name, substr_count($this->name, '.') - 1); $this->name = preg_replace('/ /', '%20', $this->name); } } function getName() { return $this->name; } function setContentType($contentType) { $this->contentType = $contentType; } function getContentType() { if (is_null($this->contentType)) $this->contentType = "application/octet-stream"; return $this->contentType; } function getETag() { $etag = md5_file($this->filepath); $etag = substr($etag, 0, . '-' . substr($etag, 8, 7) . '-' . substr($etag, 15, 8); return $etag; } function getLastModified() { return date("D, d M Y H:i:s T", filemtime($this->filepath)); } function getRequestRange() { global $_SERVER; $requestRange->rangeLength = $requestRange->fileLength = $this->getFilesize($this->filepath); $requestRange->rangeStart = 0; $requestRange->rangeEnd = $requestRange->rangeLength - 1; $requestRange->isPartial = isset($_SERVER["HTTP_RANGE"]) ? true:false; $httpRange = $_SERVER["HTTP_RANGE"]; if ($requestRange->isPartial) { list($type, $ranges) = explode("=", $httpRange); $ranges = explode(",", $ranges); $range = trim($ranges[0]); list($start, $end) = explode("-", $range); if (strlen($start) != 0) $requestRange->rangeStart = doubleval($start); else if (strlen($start) == 0 && strlen($end) != 0) $requestRange->rangeStart = $requestRange->rangeEnd - doubleval($end); if (strlen($end) != 0) $requestRange->rangeEnd = doubleval($end); } $requestRange->rangeLength = $requestRange->rangeEnd - $requestRange->rangeStart + 1; return $requestRange; } function header($value) { header($value); } function getFilesize($path) { return doubleval(sprintf("%u", filesize($path))); } } } ?>