From: Michael Wallner Date: Tue, 6 Dec 2005 13:54:02 +0000 (+0000) Subject: - add an "Download big file" example X-Git-Tag: RELEASE_0_20_0~52 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=c19bc275a7b59983992d018e5f74e7e4822c8035;p=m6w6%2Fext-http - add an "Download big file" example --- diff --git a/docs/examples/tutorial.txt b/docs/examples/tutorial.txt index fbe9f21..d2a8cf1 100644 --- a/docs/examples/tutorial.txt +++ b/docs/examples/tutorial.txt @@ -341,4 +341,130 @@ class FeedAggregator } ?> +- Download a big file + +saveTo('file.bin'); +*/ + +class BiggetRequest extends HttpRequest +{ + public $id; +} + +class Bigget extends HttpRequestPool +{ + const SIZE = 1048576; + + private $url; + private $size; + private $count = 0; + private $files = array(); + + static function url($url) + { + $head = new HttpRequest($url, HttpRequest::METH_HEAD); + $headers = $head->send()->getHeaders(); + $head = null; + + if (!isset($headers['Accept-Ranges'])) { + throw new HttpExcpetion("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->size = $headers['Content-Length']; + return $bigget; + } + + function saveTo($file) + { + $this->send(); + if ($w = fopen($file, 'wb')) { + echo "\nCopying temp files to $file ...\n"; + foreach (glob("bigget_????.tmp") as $tmp) { + echo "\t$tmp\n"; + if ($r = fopen($tmp, 'rb')) { + stream_copy_to_stream($r, $w); + fclose($r); + } + unlink($tmp); + } + fclose($w); + echo "\nDone.\n"; + } + } + + function send() + { + // use max 3 simultanous requests with a req size of 1MiB + while ($this->count < 3 && -1 != $offset = $this->getRangeOffset()) { + $this->attachNew($offset); + } + + while ($this->socketPerform()) { + if (!$this->socketSelect()) { + throw new HttpSocketException; + } + } + } + + private function attachNew($offset) + { + $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1; + + echo "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; + } + + protected function socketPerform() + { + try { + $rc = 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("bigget_%04d.tmp", $r->id), $r->getResponseBody()); + + if (-1 != $offset = $this->getRangeOffset()) { + $this->attachNew($offset); + } + } + + return $rc; + } +} +?>