X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=lib%2FBigGet.php;h=73049a6cc7fad449f95e2cf0a22ecef821e1805a;hp=e61ef7e2cb3ec4b5928b50a507e78403bace0e41;hb=f39ea2b145caa37d9614a8a437ffd3d8914b52f0;hpb=e78857a010ae86f5dddb593cbe96d67e5bd6f13d diff --git a/lib/BigGet.php b/lib/BigGet.php index e61ef7e..73049a6 100644 --- a/lib/BigGet.php +++ b/lib/BigGet.php @@ -13,197 +13,191 @@ class BigGet extends HttpRequestPool /** * File split size */ - const SIZE = 1048576; - - /** - * Parallel Request count - */ - const RMAX = 5; - - /** - * Whether to output debug messages - * - * @var bool - */ - public $dbg = false; - - /** - * URL - * - * @var string - */ - private $url; - - /** - * Temp file prefix - * - * @var string - */ - private $tmp; - - /** - * Size of requested resource - * - * @var int - */ - private $size; - - /** - * Whether the requests have been sent - * - * @var bool - */ - private $sent = false; - - /** - * Request counter - * - * @var int - */ - private $count = 0; - - /** - * Static constructor - * - * @param string $url - * @param string $tmp - * @return BigGet - * @throws Exception - */ - public static function url($url, $tmp = '/tmp') - { - $head = new HttpRequest($url, HttpRequest::METH_HEAD); - $headers = $head->send()->getHeaders(); - - if (200 != $head->getResponseCode()) { - throw new HttpException("Did not receive '200 Ok' from HEAD $url"); - } - if (!isset($headers['Accept-Ranges'])) { - throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url"); - } - if (!isset($headers['Content-Length'])) { - throw new HttpException("Did not receive a Content-Length header from HEAD $url"); - } - - $bigget = new BigGet; - $bigget->url = $url; - $bigget->tmp = tempnam($tmp, 'BigGet.'); - $bigget->size = $headers['Content-Length']; - return $bigget; - } - - /** - * Save the resource to a file - * - * @param string $file - * @return bool - * @throws Exception - */ - public function saveTo($file) - { - $this->sent or $this->send(); - - if ($w = fopen($this->tmp, 'wb')) { - - $this->dbg && print "\nCopying temp files to $file ...\n"; - - foreach (glob($this->tmp .".????") as $tmp) { - - $this->dbg && print "\t$tmp\n"; - - if ($r = fopen($tmp, 'rb')) { - stream_copy_to_stream($r, $w); - fclose($r); - } - unlink($tmp); - } - fclose($w); - rename($this->tmp, $file); - - $this->dbg && print "\nDone.\n"; - - return true; - } - return false; - } - - /** - * Overrides HttpRequestPool::send() - * - * @return void - * @throws Exception - */ - public function send() - { - $this->sent = true; - - // use max RMAX simultanous requests with a req size of SIZE - while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) { - $this->attachNew($offset); - } - - while ($this->socketPerform()) { - if (!$this->socketSelect()) { - throw new HttpSocketException; - } - } - } - - /** - * Overrides HttpRequestPool::socketPerform() - * - * @return bool - */ - protected function socketPerform() - { - try { - $rs = parent::socketPerform(); - } catch (HttpRequestPoolException $x) { - foreach ($x->exceptionStack as $e) { - echo $e->getMessage(), "\n"; - } - } - - foreach ($this->getFinishedRequests() as $r) { - $this->detach($r); - - if (206 != $rc = $r->getResponseCode()) { - throw new HttpException("Unexpected response code: $rc"); - } - - file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody()); - - if (-1 != $offset = $this->getRangeOffset()) { - $this->attachNew($offset); - } - } - - return $rs; - } - - private function attachNew($offset) - { - $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1; - - $this->dbg && print "Attaching new request to get range: $offset-$stop\n"; - - $req = new BigGetRequest( - $this->url, - HttpRequest::METH_GET, - array( - 'headers' => array( - 'Range' => "bytes=$offset-$stop" - ) - ) - ); - $this->attach($req); - $req->id = $this->count++; - } - - private function getRangeOffset() - { - return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1; - } + const SIZE = 1048576; + + /** + * Parallel Request count + */ + const RMAX = 5; + + /** + * Whether to output debug messages + * + * @var bool + */ + public $dbg = false; + + /** + * URL + * + * @var string + */ + private $url; + + /** + * Temp file prefix + * + * @var string + */ + private $tmp; + + /** + * Size of requested resource + * + * @var int + */ + private $size; + + /** + * Whether the requests have been sent + * + * @var bool + */ + private $sent = false; + + /** + * Request counter + * + * @var int + */ + private $count = 0; + + /** + * Static constructor + * + * @param string $url + * @param string $tmp + * @return BigGet + * @throws Exception + */ + public static function url($url, $tmp = '/tmp') + { + $head = new HttpRequest($url, HttpRequest::METH_HEAD); + $headers = $head->send()->getHeaders(); + + if (200 != $head->getResponseCode()) { + throw new HttpException("Did not receive '200 Ok' from HEAD $url"); + } + if (!isset($headers['Accept-Ranges'])) { + throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url"); + } + if (!isset($headers['Content-Length'])) { + throw new HttpException("Did not receive a Content-Length header from HEAD $url"); + } + + $bigget = new BigGet; + $bigget->url = $url; + $bigget->tmp = tempnam($tmp, 'BigGet.'); + $bigget->size = $headers['Content-Length']; + return $bigget; + } + + /** + * Save the resource to a file + * + * @param string $file + * @return bool + * @throws Exception + */ + public function saveTo($file) + { + $this->sent or $this->send(); + + if ($w = fopen($this->tmp, 'wb')) { + + $this->dbg && print "\nCopying temp files to $file ...\n"; + + foreach (glob($this->tmp .".????") as $tmp) { + + $this->dbg && print "\t$tmp\n"; + + if ($r = fopen($tmp, 'rb')) { + stream_copy_to_stream($r, $w); + fclose($r); + } + unlink($tmp); + } + fclose($w); + rename($this->tmp, $file); + + $this->dbg && print "\nDone.\n"; + + return true; + } + return false; + } + + /** + * Overrides HttpRequestPool::send() + * + * @return void + * @throws Exception + */ + public function send() + { + $this->sent = true; + + // use max RMAX simultanous requests with a req size of SIZE + while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) { + $this->attachNew($offset); + } + + while ($this->socketPerform()) { + if (!$this->socketSelect()) { + throw new HttpSocketException; + } + } + } + + /** + * Overrides HttpRequestPool::socketPerform() + * + * @return bool + */ + protected function socketPerform() + { + $rs = parent::socketPerform(); + + foreach ($this->getFinishedRequests() as $r) { + $this->detach($r); + + if (206 != $rc = $r->getResponseCode()) { + throw new HttpException("Unexpected response code: $rc"); + } + + file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody()); + + if (-1 != $offset = $this->getRangeOffset()) { + $this->attachNew($offset); + } + } + + return $rs; + } + + private function attachNew($offset) + { + $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1; + + $this->dbg && print "Attaching new request to get range: $offset-$stop\n"; + + $req = new BigGetRequest( + $this->url, + HttpRequest::METH_GET, + array( + 'headers' => array( + 'Range' => "bytes=$offset-$stop" + ) + ) + ); + $this->attach($req); + $req->id = $this->count++; + } + + private function getRangeOffset() + { + return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1; + } } @@ -213,7 +207,7 @@ class BigGet extends HttpRequestPool */ class BigGetRequest extends HttpRequest { - public $id; + public $id; } ?>