【问题标题】:Download large file chunk by chunk with php curl使用 php curl 逐块下载大文件
【发布时间】:2012-10-21 00:29:00
【问题描述】:

我需要 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);

}

?>

【问题讨论】:

标签: php curl


【解决方案1】:

如果您的意图是通过不稳定的连接下载文件,curl 有一个 --retry 标志以在出现错误时自动重试下载并从中断处继续。不幸的是,它似乎是PHP library is missing that option,因为libcurl is also missing that option

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

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

【讨论】:

    【解决方案2】:

    这是我使用 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 的问题,那就太好了!
    • @SimasJoneliunas 感谢您指出这一点,我在代码中添加了 cmets
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    • 2011-05-16
    • 2015-08-04
    相关资源
    最近更新 更多