PHP实现文件断点续传下载

<?php
//PHP 断点续传下载
function download($fileurl, $start = 0, $end = '')
{
    $task_sourcefile = '/path/downfile.mp4'; //本地保存的文件
        $sourceurl = $fileurl ;  //要下载的远程文件
        $tokenfile =  'downfile.token';
    $isfileexist =$this->check_remote_file_exists($sourceurl);
    if (!$isfileexist) {
        $isfileexist2 =$this->check_remote_file_exists($sourceurl);
        if (!$isfileexist2) {
            throw new \Exception('远程文件不存在');
        }
    }
    if (!is_dir(dirname($tokenfile))) {
        mkdir(dirname($tokenfile), 0777, true);
    }
    $sourcefilepath = dirname($task_sourcefile);
  
    if (!is_dir($sourcefilepath)) {
        @mkdir($sourcefilepath, 0777, true);
    }
        
    $ch = curl_init($sourceurl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_USERAGENT, 'SyncTask');
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1); //注意,超时一定要设置这个
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 3600);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
    curl_setopt($ch, CURLOPT_TIMEOUT, 600); //此选项,是下载超时时间,时间设置短的话,没有下载完,就会断开连接,然后再重新断点续传下载。如果设置过长,可能会发生由于网络原因产生的下载长时间卡住 的现象。请设置合理值。建议不要设置太长。
    //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100 * 1000); //超时毫秒
    curl_setopt($ch, CURLOPT_BUFFERSIZE, 20971520);
    if ($end) {
        curl_setopt($ch, CURLOPT_RANGE, "$start-$end");
    } else {
        curl_setopt($ch, CURLOPT_RANGE, "$start-");
    }
        
    $flag=$tag = 0;

    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $str) use (&$flag, $task_sourcefile, $end, $sourceurl, $tokenfile, $start, &$tag) {
        $len = strlen($str);
        $flag++;
        if ($flag==1) {
            $httpcode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $length  = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
            if ($length ==-1) {
                $tag = 2;
                return false;
            }
            if ($httpcode!=200 && $httpcode!=206) {
                $tag = 2;
                return false;
            }
            if ($start ==0) {
                $data= ['name'=>$sourceurl,'size'=>$length];
                file_put_contents($tokenfile, json_encode($data, JSON_UNESCAPED_UNICODE));
            }
            if ($end) {
                if ($end-$start!=$length) {
                    $tag = 1;
                    return false;
                }
            }
        }
        file_put_contents($task_sourcefile, $str, FILE_APPEND|LOCK_EX);
        return $len;
    });
    $output = curl_exec($ch);
    if ($tag ==2 || $output===false) {
        curl_close($ch);
        clearstatcache();
        download($fileurl, filesize($task_sourcefile), '');
    }
    if ($tag ==1) {
        unlink($task_sourcefile);
        unlink($tokenfile);
        curl_close($ch);
        download($fileurl, 0, '');
        return true;
    }
         
    $tokeninfo  = json_decode(file_get_contents($tokenfile), true);
    $length = $tokeninfo['size'];
    sleep(1);
    clearstatcache();//这里要去除文件信息缓存
    if ($length!= filesize($task_sourcefile)) {
        curl_close($ch);
        echo '下载出错:长度不长度不匹配~~';
        clearstatcache();
        download($fileurl, filesize($task_sourcefile), '');
    }
    curl_close($ch);
    return true;
}
 
    //run
   $download= download('http://www.test.com/333.mp4');
   var_dump($download);

 

原创文章,转载请注明来自Lenix的博客,地址 http://blog.p2hp.com/archives/5441

 

最后更新于 2019年8月8日

PHP实现文件断点续传下载
标签: