使用 PHP Curl 分块下载大文件

4
我需要一份php脚本,用于从url到服务器的可恢复文件下载。它应该能够启动下载,然后当它中断(30秒至5分钟)时恢复下载,直到完成整个文件。
在perl中有类似的东西 http://curl.haxx.se/programs/download.txt ,但我想在php中实现它,我不会perl。
我认为可以使用CURLOPT_RANGE下载块,并使用fopen($fileName, "a")将其附加到服务器上的文件。
这是我的尝试:
<?php

function run()
{
    while(1)
    {
         get_chunk($_SESSION['url'], $_SESSION['filename']);
         sleep(5);
         flush();
    }    
}

function get_chunk( $url, $fileName)
{

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    if (file_exists($fileName)) {
        $from = filesize($fileName);
        curl_setopt($ch, CURLOPT_RANGE, $from . "-");//maybe "-".$from+1000 for 1MB chunks
    }

    $fp = fopen($fileName, "a");
    if (!$fp) {
        exit;
    }
    curl_setopt($ch, CURLOPT_FILE, $fp);
    $result = curl_exec($ch);
    curl_close($ch);

    fclose($fp);

}

?>

这将会有所帮助。https://dev59.com/HnI-5IYBdhLWcg3wED9V - kpotehin
2个回答

0

这是我使用 PHP 实现的分块文件下载解决方案,不使用 curl,而是使用 fopen:

//set the chunnk size, how much would you like to transfer in one go
$chunksize = 5 * (1024 * 1024);
//open your local file with a+ access (appending to the file = writing at end of file)
$fp = fopen ($local_file_name, 'a+');
if($fp === false)
{
    //error handling, local file cannot be openened
}
else
{
    //open remote file with read permission, you need to have allow_url_fopen to be enabled on our server if you open here a URL
    $handle = fopen($temp_download, 'rb');
    if($handle === false)
    {
        //error handling, remote file cannot be opened
    }
    else
    {
        //while we did not get to the end of the read file, loop
        while (!feof($handle))
        { 
            //read a chunk of the file
            $chunk_info = fread($handle, $chunksize);
            if($chunk_info === false)
            {
                //error handling, chunk reading failed
            }
            else
            {
                //write the chunk info we just read to the local file
                $succ = fwrite($fp, $chunk_info);
                if($succ === false)
                {
                    //error handling, chunk info writing locally failed
                }
            }
        } 
        //close handle
        fclose($handle);
    }
}
//close handle
fclose($fp); 

嗨,如果您能帮助我们理解您的代码是如何解决 OP 的问题的,那将非常棒! - Simas Joneliunas
@SimasJoneliunas谢谢您指出这一点,我已经在代码中添加了注释。 - CodeRevolution

0
如果你的意图是在不稳定的连接上下载文件,curl有一个--retry标志,在出现错误时自动重试下载并继续之前的进度。不幸的是,似乎PHP library缺少该选项因为libcurl也缺少该选项
通常我建议使用库而不是外部命令,但在这种情况下,与其自己编写代码,还不如直接在命令行中调用 curl --retrycurl -C -wget -c是另一个选择。
否则,我认为没有必要总是将数据分块获取。尽可能多地下载,如果出现错误,请使用CURLOPT_RANGE和文件大小来恢复之前的进度。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接