«

php实现分段下载

时间:2024-2-21 13:16     作者:韩俊     分类: PHP


php实现分段下载。

<?php

$url = 'https://www.maopiaopiao.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);
}

标签: php php教程

热门推荐