php利用多线程下载文件示例。
<?php /** * php利用多线程下载文件示例 * 还可以参考:https://docs.guzzlephp.org/en/stable/request-options.html#stream * author:https://www.phpernote.com/ */ $url = 'https://www.phpernote.com/image/shop.zip'; $st = time(); download($url, 50); //file_put_contents('./file1', file_get_contents($url)); $et = time(); echo '耗时:' . ($et - $st) . '秒'; /** * 获取文件大小 * @param $url * @return mixed|string */ function getFileSize($url) { $ch = curl_init(); $headerData = [ "Range: bytes=0-1" ]; curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData); //curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD"); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't print curl_setopt($ch, CURLOPT_TIMEOUT, 0); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect curl_setopt($ch, CURLOPT_MAXREDIRS, 7); curl_setopt($ch, CURLOPT_HEADER, true);//需要获取header头 curl_setopt($ch, CURLOPT_NOBODY, 1); //不需要body,只需要获取header头的文件大小 $sContent = curl_exec($ch); // 获得响应结果里的:头大小 $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);//获取header头大小 // 根据头大小去获取头信息内容 $header = substr($sContent, 0, $headerSize);//获取真实的header头 curl_close($ch); $headerArr = explode("\r\n", $header); foreach ($headerArr as $item) { $value = explode(':', $item); if ($value[0] == 'Content-Range') {//通过分段,获取到文件大小 $fileSize = explode('/', $value[1])[1];//文件大小 break; } } return $fileSize; } /** * 下载文件 * @param $url * @param int $process_num 线程数 */ function download($url, $process_num = 5) { $fileSize = getFileSize($url); //开启多线程下载 $mh = curl_multi_init(); $handle = [];//n线程数组 $data = [];//数据分段数组 $fileData = ceil($fileSize / $process_num); for ($i = 0; $i < $process_num; $i++) { $ch = curl_init(); //判断是否读取数量大于剩余数量 if ($fileData > ($fileSize - ($i * $fileData))) { $headerData = [ "Range:bytes=" . $i * $fileData . "-" . ($fileSize) ]; } else { $headerData = [ "Range:bytes=" . $i * $fileData . "-" . (($i + 1) * $fileData) ]; } //echo PHP_EOL; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't print curl_setopt($ch, CURLOPT_TIMEOUT, 0); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData); curl_setopt($ch, CURLOPT_MAXREDIRS, 7); curl_multi_add_handle($mh, $ch); // 把 curl resource 放进 multi curl handler 里 $handle[$i] = $ch; } $active = null; do { //同时执行多线程,直到全部完成或超时 $mrc = curl_multi_exec($mh, $active); } while ($active); for ($i = 0; $i < $process_num; $i++) { $data[$i] = curl_multi_getcontent($handle[$i]); curl_multi_remove_handle($mh, $handle[$i]); } curl_multi_close($mh); $file = implode('', $data);//组合成一个文件 file_put_contents('./file', $file); }