19 08 22

<?php

$url = 'https://www.phpernote.com/image/shop.zip';

$st = time();
download($url, 3);
//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);
}

转载于:https://www.phpernote.com/php-function/1690.html

延伸阅读
  1. php 数字加大写字母按顺序编号 00 - ZZ
  2. 计算两个日期之间相差时长
  3. PHP RC4算法加解