url = $url; $this->params = $params; $this->method = $method; $this->http = new HttpRequest(); } /** * 获取文件大小,单位:字节。 * @return mixed */ public function getFileSize() { $this->response = $this->http->headers(array( 'Range' => 'bytes=0-1', ))->options(array( CURLOPT_NOBODY => true ))->send($this->url, $this->params, $this->method); if (isset($this->response->headers['Content-Range'])) { list(, $length) = explode('/', $this->response->headers['Content-Range']); return (int) $length; } else { return false; } } public function download($filename) { $this->fileSize = $this->getFileSize(); if ($this->fileSize) { $canBreakContinue = isset($this->response->headers['Content-Range']); switch ($this->breakContinue) { case BreakContinue::AUTO: $this->isBreakContinue = $canBreakContinue; break; case BreakContinue::ON: $this->isBreakContinue = (true === $canBreakContinue); break; case BreakContinue::OFF: $this->isBreakContinue = false; break; } } else { $canBreakContinue = $this->isBreakContinue = false; } $this->http->options(array( CURLOPT_NOBODY => false )); if ($this->isBreakContinue) { $fp = fopen($filename, 'a+'); if (false === $fp) { throw new \Exception('打开本地文件失败'); } $begin = filesize($filename); if (false === $begin) { throw new \Exception('获取本地文件大小失败'); } while ($begin < $this->fileSize) { $length = min($this->fileSize - $begin, $this->blockSize); $this->response = $this->http->headers(array( 'Range' => 'bytes=' . $begin . '-' . ($begin + $length), ))->send($this->url, $this->params, $this->method); if (false === fwrite($fp, $this->response->body)) { fclose($fp); throw new \Exception('文件写入失败'); } $begin += $this->response->headers['Content-Length']; $this->trigger('progressChanged', array( 'length' => $this->fileSize, 'completeLength' => $begin, 'percent' => $begin / $this->fileSize, )); } fclose($fp); } else { $this->http->download($filename, $this->url, $this->params, $this->method); } } } try { $download = new Download('http://dldir1.qq.com/weixin/Windows/WeChatSetup.exe'); $download->blockSize = 1048576; // 每一块数据的大小,可以不设置,默认为1M // 绑定每一块数据下载完成事件 $download->on('progressChanged', function($e) { var_dump($e); }); // 获取文件大小 echo $download->getFileSize(), PHP_EOL; // 下载 $download->download(__DIR__ . '/1.exe'); // 获取是否使用断点续传分块下载 var_dump($download->isBreakContinue); } catch (\Exception $e) { var_dump($e->getMessage()); }