3

我需要用于从 url 到服务器的可恢复文件下载的 php 脚本。它应该能够开始下载,然后在捕捉(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);

}

?>
4

2 回答 2

0

如果您的意图是通过不稳定的连接下载文件,请curl设置一个--retry标志以在出现错误时自动重试下载并从中断处继续。不幸的是, PHP 库似乎缺少该选项,因为libcurl 也缺少该选项

通常我建议使用库而不是外部命令,但与其滚动你自己的命令,在这种情况下调用curl --retrycurl -C -在命令行上可能更简单。 wget -c是另一种选择。

否则,我认为不需要始终以块的形式获取数据。尽可能多地下载,如果有错误继续使用 CURLOPT_RANGE 和文件大小,就像现在一样。

于 2012-10-21T00:54:39.980 回答
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); 
于 2022-01-13T09:27:25.070 回答