В PHP можно несколькими вариантами загрузить файл по ссылке (URL) и сохранить на сервере. Некоторые из них имеют важные отличия, которые могут стать ключевыми при выборе способа скачать и сохранить файл в PHP.
1. file_get_contents и file_put_contents
Первый весьма очевидный вариант — использовать file_get_contents и file_put_contents:
file_put_contents("Tmpfile.zip", file_get_contents("http://someurl/file.zip"));
Реальный пример:
file_put_contents("mial.jpg", file_get_contents("https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg"));
Недостаток этого метода — до сохранения на диск файл полностью хранится в оперативной памяти. Если вы загружаете очень большой файл (размером в гигабайты), то вы можете столкнуться с проблемой нехватки памяти на сервере которая выделена для выполнения одного скрипта.
2. fopen и file_put_contents для немедленной записи данных на диск по мере их поступления
Если для вас важно, чтобы оперативная память не была переполнена при загрузке большого файла, то используйте комбинацию fopen и file_put_contents:
file_put_contents("Tmpfile.zip", fopen("http://someurl/file.zip", 'r'));
В этом случае файл будет записываться на диск по мере скачивания и не будет держаться в оперативной памяти вплоть до окончания загрузки.
Реальный пример:
file_put_contents("mial2.jpg", fopen("https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg", 'r'));
Но у этого способа есть и недостаток — в настройках PHP значение allow_fopen_url может быть установлено на Off. В данном случае указанная конструкция не будет работать из-за запрета открытия файлов с помощью fopen если файл указан как URL.
3. Пользовательская функция для загрузки файлов с помощью PHP
Если вам нужна максимальная гибкость, то вы можете использовать следующую функцию. Обратите внимание, что вы можете настроить фрагментами какого именно размера файл должен считываться и записываться:
function downloadFile($url, $path)
{
$newfname = $path;
$file = fopen ($url, 'rb');
if ($file) {
$newf = fopen ($newfname, 'wb');
if ($newf) {
while(!feof($file)) {
fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
}
}
}
if ($file) {
fclose($file);
}
if ($newf) {
fclose($newf);
}
}
Реальный рабочий пример кода:
<?php
function downloadFile($url, $path)
{
$newfname = $path;
$file = fopen ($url, 'rb');
if ($file) {
$newf = fopen ($newfname, 'wb');
if ($newf) {
while(!feof($file)) {
fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
}
}
}
if ($file) {
fclose($file);
}
if ($newf) {
fclose($newf);
}
}
downloadFile ('https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg', 'mial3.jpg');
4. Использование библиотеки curl для загрузки файла в PHP
Библиотека curl поддерживает множество протоколов, также вы можете настроить пользовательский User Agent, вы можете использовать аутентификацию и кукиз.
Смотрите также: PHP cURL как установить значение User Agent ИЛИ как сделать так, чтобы сервера не блокировали запросы cURL
Пример скачивания файла с помощью PHP библиотеки curl:
function downloadUrlToFile($url, $outFileName) {
if(is_file($url)) {
copy($url, $outFileName);
}
else {
$options = array(
CURLOPT_FILE => fopen($outFileName, 'w'),
CURLOPT_TIMEOUT => 28800, // set this to 8 hours so we dont timeout on big files
CURLOPT_URL => $url
);
$ch = curl_init();
curl_setopt_array($ch, $options);
curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpcode;
}
}
Реальный рабочий пример кода:
function downloadUrlToFile($url, $outFileName) {
if(is_file($url)) {
copy($url, $outFileName);
}
else {
$options = array(
CURLOPT_FILE => fopen($outFileName, 'w'),
CURLOPT_TIMEOUT => 28800, // set this to 8 hours so we dont timeout on big files
CURLOPT_URL => $url
);
$ch = curl_init();
curl_setopt_array($ch, $options);
curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpcode;
}
}
downloadUrlToFile ('https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg', 'mial4.jpg');
5. Загрузка файлов в PHP с использованием wget
exec ('wget http://someurl/file.zip');
Реальный рабочий пример кода:
exec ('wget https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg');
Вам необходимо убедиться, что утилита wget установлена на сервере и доступна для запуска из PHP скрипта.
При использовании данного варианта файл сохраняется на диск по мере загрузки и не переполняет оперативную память.
Во время работы скрипта выводится информация wget, в том числе прогресс загрузки файла.
Необязательно указывать имя файла — по умолчанию будет использоваться исходное имя. При желании, вы можете явно указать имя файла с помощью опции «-O»:
exec ('wget -O mial5.jpg https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg');
6. Загрузка файлов в PHP с использованием утилиты cURL
Вы можете использовать утилиту Linux cURL — по аналогии, как мы использовали утилиту wget в предыдущем примере.
Возможности PHP библиотеки curl и Linux утилиты cURL весьма схожи. Но этот метод следует выделить в отдельную группу, поскольку многим намного удобнее синтаксис командной строки cURL чем замысловатый синтаксис PHP библиотеки curl.
К примеру, вместо всех замысловатых конструкций рассмотренных выше для PHP библиотеки curl аналогичного результата можно добиться с помощью следующей строки кода:
exec ('curl -o Tmpfile.zip http://someurl/file.zip');
Вы по-прежнему можете использовать различные протоколы, аутентификацию, POST запросы, изменение реферера и User Agent, кукиз и все прочие многочисленные возможности cURL. Но при этом вам не нужно заново осваивать синтаксис PHP библиотеки curl — вы можете использовать привычный синтаксис командной строки.
Реальный рабочий пример кода:
exec ('curl -o mial6.jpg https://suay.ru/wp-content/uploads/2024/03/20231213_151132.jpg');
Обратите внимание, опция «-o» с указанием имени файла является обязательной для бинарных файлов (да и для текстовых тоже, поскольку без указания этой опции содержимое файла будет выведено в стандартный вывод без сохранения на диске).
