使用curl下载大文件


86

我需要使用curl下载远程文件。

这是我的示例代码:

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

$st = curl_exec($ch);
$fd = fopen($tmp_name, 'w');
fwrite($fd, $st);
fclose($fd);

curl_close($ch);

但是它不能处理大文件,因为它首先读取内存。

是否可以将文件直接流式传输到磁盘?

Answers:


167
<?php
set_time_limit(0);
//This is the file where we save the    information
$fp = fopen (dirname(__FILE__) . '/localfile.tmp', 'w+');
//Here is the file we are downloading, replace spaces with %20
$ch = curl_init(str_replace(" ","%20",$url));
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
// write curl response to file
curl_setopt($ch, CURLOPT_FILE, $fp); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// get curl response
curl_exec($ch); 
curl_close($ch);
fclose($fp);
?>

5
捍卫您的评论@ yes123,我很想知道。
尔根·保罗(

8
如果我错了,请纠正我,但fwrite由于您使用,我认为您实际上并不需要手动处理数据CURLOPT_FILE
Sasha Chedygov

1
正如@SashaChedygov在上面指出的那样,您不需要使用fwriteAND CURLOPT_FILE。通过$fp足够了。我都做了,最后1是文件内容的结尾。
回形针

@Sasha Chedygov〜是的,您不需要fwrite
Alireza

5
似乎在设置CURLOPT_RETURNTRANSFER之前设置CURLOPT_FILE不起作用,大概是因为CURLOPT_FILE取决于所设置的CURLOPT_RETURNTRANSFER。php.net/manual/en/function.curl-setopt.php#99082
Nabi KAZ)

25

我使用这个方便的功能:

如果以4094字节的步长下载它,将不会占用您的全部内存

function download($file_source, $file_target) {
    $rh = fopen($file_source, 'rb');
    $wh = fopen($file_target, 'w+b');
    if (!$rh || !$wh) {
        return false;
    }

    while (!feof($rh)) {
        if (fwrite($wh, fread($rh, 4096)) === FALSE) {
            return false;
        }
        echo ' ';
        flush();
    }

    fclose($rh);
    fclose($wh);

    return true;
}

用法:

     $result = download('http://url','path/local/file');

然后,您可以使用以下方法检查一切是否正常:

     if (!$result)
         throw new Exception('Download error...');

1
@Severus,您发现http错误为fopen()返回false并超时,并将其放入while循环(调用time()并进行数学运算)
Silviu-Marian 2012年

2
cURL已经有此功能的有效实现(请参见接受的答案),为什么您要自己实现某些功能?
Petr Peller

2
由于cURL程序接口非常糟糕
动态的

对于它的价值,我一直在使用stream_copy_to_stream而不是手动复制内容的方法来编写较短的代码。这和那都不起作用https(除非您规定$context)。一致的程序样式-文件功能也不是完全面向对象的,并且,如果将curl选项放在数组中,无论如何它看起来都会更干净。
ashein

我用https测试了它,效果很好!!!感谢您的帮助@dynamic。
Ozal Zarbaliyev,

6

如果要下载指定URL的内容,也想将其保存到文件中,请查找以下代码。

<?php
$ch = curl_init();
/**
* Set the URL of the page or file to download.
*/
curl_setopt($ch, CURLOPT_URL,'http://news.google.com/news?hl=en&topic=t&output=rss');

$fp = fopen('rss.xml', 'w+');
/**
* Ask cURL to write the contents to a file
*/
curl_setopt($ch, CURLOPT_FILE, $fp);

curl_exec ($ch);

curl_close ($ch);
fclose($fp);
?>

如果要从FTP服务器下载文件,则可以使用php FTP扩展名。请找到以下代码:

<?php
$SERVER_ADDRESS="";
$SERVER_USERNAME="";
$SERVER_PASSWORD="";
$conn_id = ftp_connect($SERVER_ADDRESS);

// login with username and password
$login_result = ftp_login($conn_id, $SERVER_USERNAME, $SERVER_PASSWORD);

$server_file="test.pdf" //FTP server file path 
$local_file = "new.pdf"; //Local server file path 

##----- DOWNLOAD $SERVER_FILE AND SAVE TO $LOCAL_FILE--------##
if (ftp_get($conn_id, $local_file, $server_file, FTP_BINARY)) {
    echo "Successfully written to $local_file\n";
} else {
    echo "There was a problem\n";
}

ftp_close($conn_id);
?>

4

curl用于下载大文件时,这CURLOPT_TIMEOUT是您必须设置的主要选项。

CURLOPT_RETURNTRANSFER 如果您要获取pdf / csv / image等文件,则必须为true。

您可以在此处找到更多详细信息(正确的网址)Curl Doc

从该页面:

curl_setopt($request, CURLOPT_TIMEOUT, 300); //set timeout to 5 mins

curl_setopt($request, CURLOPT_RETURNTRANSFER, true); // true to get the output as string otherwise false

ü也可以去通过博客例如关于与卷曲的文件下载的理解卷曲基础
PRASHANT潘迪

2

您可以使用此函数,如果一切正常,它将在文件系统中创建一个临时文件,并返回下载文件的路径:

function getFileContents($url)
{
    // Workaround: Save temp file
    $img = tempnam(sys_get_temp_dir(), 'pdf-');
    $img .= '.' . pathinfo($url, PATHINFO_EXTENSION);

    $fp = fopen($img, 'w+');

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    $result = curl_exec($ch);
    curl_close($ch);

    fclose($fp);

    return $result ? $img : false;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.