Ответ 1
Вам нужно явно записать файл с помощью fwrite
, передав ему ранее созданный дескриптор файла:
if ( $httpCode == 404 ) {
...
} else {
$contents = curl_exec($curl);
fwrite($fp, $contents);
}
curl_close($curl);
fclose($fp);
Я хочу попробовать подключиться к удаленному файлу и записать вывод оттуда в локальный файл, это моя функция:
function get_remote_file_to_cache()
{
$the_site="http://facebook.com";
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w");
curl_setopt ($curl, CURLOPT_URL, $the_site);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_exec ($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
touch('cache/404_err.txt');
}else
{
touch('cache/'.rand(0, 99999).'--all_good.txt');
}
curl_close ($curl);
}
Он создает два файла в каталоге "cache", но проблема в том, что он не записывает данные в "temp_file.txt", почему это?
Спасибо!
R
Вам нужно явно записать файл с помощью fwrite
, передав ему ранее созданный дескриптор файла:
if ( $httpCode == 404 ) {
...
} else {
$contents = curl_exec($curl);
fwrite($fp, $contents);
}
curl_close($curl);
fclose($fp);
Собственно, использование fwrite частично верно. Чтобы избежать проблем с переполнением памяти большими файлами (превышен максимальный предел памяти для PHP), вам необходимо настроить функцию обратного вызова для записи в файл.
ПРИМЕЧАНИЕ.. Я бы рекомендовал создать класс специально для обработки файлов и файлов и т.д., а не EVER с использованием глобальной переменной, но для целей этого примера показано, как получить вещи вверх и бег.
то сделайте следующее:
# 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.
По сути, это займет каждый загруженный блок данных и немедленно выгрузит его в файл, а не сначала загрузит файл ENTIRE в память.
Более безопасный способ сделать это! Конечно, вы должны убедиться, что URL правильный (конвертировать пробелы в %20 и т.д.) И что локальный файл можно записать.
Cheers, Джеймс.
Попробуйте отправить запрос GET на http://facebook.com
:
$ curl -v http://facebook.com * Rebuilt URL to: http://facebook.com/ * Hostname was NOT found in DNS cache * Trying 69.171.230.5... * Connected to facebook.com (69.171.230.5) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.35.0 > Host: facebook.com > Accept: */* > < HTTP/1.1 302 Found < Location: https://facebook.com/ < Vary: Accept-Encoding < Content-Type: text/html < Date: Thu, 03 Sep 2015 16:26:34 GMT < Connection: keep-alive < Content-Length: 0 < * Connection #0 to host facebook.com left intact
Что случилось? Похоже, что Facebook перенаправил нас с http://facebook.com
на https://facebook.com/
. Обратите внимание на то, что длина тела ответа:
Content-Length: 0
Это означает, что нулевые байты будут записаны в xxxx--all_good.txt
. Вот почему файл остается пустым.
Ваше решение абсолютно верно:
$fp = fopen('file.txt', 'w');
curl_setopt($handle, CURLOPT_FILE, $fp);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
Все, что вам нужно сделать, это изменить URL-адрес на https://facebook.com/
.
Относительно других ответов:
fwrite()
после curl_exec()
CURLOPT_WRITEFUNCTION
для такой простой операции, которая копирует содержимое в файл.touch()
создает пустой файл, если он не существует. Я думаю, что это было намерение OP.Серьезно, три ответа и каждый из них недействительны?
Функция touch()
ничего не делает для содержимого файла. Он просто обновляет время модификации. Посмотрите file_put_contents() function
.
Я тоже столкнулся с этой проблемой. Это действительно глупо, но решение состоит в том, чтобы установить CURLOPT_RETURNTRANSFER перед CURLOPT_FILE!
Кажется, CURLOPT_FILE зависит от CURLOPT_RETURNTRANSFER.
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w+");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_URL, $url);
curl_exec ($curl);
curl_close($curl);
fclose($fp);