実際、fwriteの使用は部分的に正しいです。大きなファイルでのメモリオーバーフローの問題(PHPの最大メモリ制限を超えた)を回避するには、ファイルに書き込むためのコールバック関数を設定する必要があります。
注:グローバル変数を使用するのではなく、ファイルのダウンロードやファイルハンドルなどを処理するためのクラスを作成することをお勧めしますが、この例の目的のために、以下に設定を実行する方法を示します。
したがって、次のようにします。
# setup a global file pointer
$GlobalFileHandle = null;
function saveRemoteFile($url, $filename) {
global $GlobalFileHandle;
set_time_limit(0);
# Open the file for writing...
$GlobalFileHandle = fopen($filename, 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FILE, $GlobalFileHandle);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, "MY+USER+AGENT"); //Make this valid if possible
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); # optional
curl_setopt($ch, CURLOPT_TIMEOUT, -1); # optional: -1 = unlimited, 3600 = 1 hour
curl_setopt($ch, CURLOPT_VERBOSE, false); # Set to true to see all the innards
# Only if you need to bypass SSL certificate validation
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
# Assign a callback function to the CURL Write-Function
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curlWriteFile');
# Exceute the download - note we DO NOT put the result into a variable!
curl_exec($ch);
# Close CURL
curl_close($ch);
# Close the file pointer
fclose($GlobalFileHandle);
}
function curlWriteFile($cp, $data) {
global $GlobalFileHandle;
$len = fwrite($GlobalFileHandle, $data);
return $len;
}
進行状況のコールバックを作成して、ダウンロードの量/速度を表示することもできますが、CLIに出力するときに複雑になる可能性があるため、これは別の例です。
基本的に、これにより、ダウンロードされたデータの各ブロックが取得され、最初にファイル全体がメモリにダウンロードされるのではなく、すぐにファイルにダンプされます。
それを行うためのはるかに安全な方法!もちろん、URLが正しいこと(スペースを%20に変換するなど)と、ローカルファイルが書き込み可能であることを確認する必要があります。
乾杯、ジェームズ。