Как получить файл в PHP: основные функции и их применение
Способы получения файла в PHP
Основное решение: file_get_contents
Наиболее эффективный способ прочитать содержимое файла в строку - использовать функцию file_get_contents(). Она подходит для небольших и средних файлов, так как загружает всё содержимое в память.
$content = file_get_contents('example.txt');
echo $content;
Если файл не найден, функция вернёт false и вызовет предупреждение. Рекомендуется проверять результат:
if (($content = file_get_contents('example.txt')) !== false) {
echo 'Содержимое: ' . $content;
} else {
echo 'Не удалось прочитать файл';
}
Проблемы: большие файлы могут превысить лимит памяти (memory_limit). Для файлов размером более нескольких мегабайт лучше использовать потоковое чтение.
Типичные ошибки: неправильный путь (относительный/абсолютный), отсутствие прав на чтение. Решение: проверять существование файла функцией file_exists() или is_readable().
Цель: быстрое получение всего содержимого текстового файла, конфигураций, шаблонов.
Как читать файл построчно или по частям, чтобы не перегружать память?
Используйте fopen() в паре с fgets() или fread(). Это позволяет обрабатывать файл любого размера.
$handle = fopen('large.log', 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo $line;
}
fclose($handle);
} else {
echo 'Ошибка открытия файла';
}
Проблемы: забыли закрыть файл (fclose) - утечка ресурсов. Решение: использовать блок try-finally или ресурс оборачивать в класс, реализующий деструктор.
Ошибки: неверный режим ('r' вместо 'rb' для бинарных файлов на Windows может повредить данные).
Цель: чтение логов, CSV-файлов, любых данных, где не требуется весь файл в памяти.
Как получить файл целиком в виде массива строк?
Функция file() возвращает массив, каждый элемент - строка файла (с сохранением символа конца строки).
$lines = file('data.txt');
foreach ($lines as $i => $line) {
echo 'Строка ' . ($i+1) . ': ' . $line;
}
Аналогично file_get_contents, загружает весь файл в память.
Проблемы: для очень больших файлов - переполнение памяти. Решение: использовать fopen+fgets для потоковой обработки.
Типичная ошибка: не удаляются символы новой строки. Можно использовать array_map('trim', $lines).
Цель: простой разбор списков, конфигураций, где строки - самостоятельные записи.
Как сразу вывести содержимое файла в браузер без сохранения в переменную?
Функция readfile() читает файл и отправляет его напрямую в выходной поток. Полезна для скачивания файлов или вывода изображений.
$filename = 'report.pdf';
if (file_exists($filename)) {
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . basename($filename) . '"');
readfile($filename);
exit;
} else {
http_response_code(404);
echo 'Файл не найден';
}
Проблемы: отсутствие прав, выход за лимит времени выполнения для больших файлов. Решение: использовать set_time_limit(0) и flush.
Ошибки: вывод случайного содержимого до header (пробелы, BOM).
Цель: прямая передача файла клиенту, минимизация использования памяти.
Как получить файл по URL (удалённый ресурс)?
Включите allow_url_fopen и используйте file_get_contents() с URL. Для более тонкого управления используйте cURL.
$url = 'https://example.com/data.json';
$json = file_get_contents($url);
if ($json !== false) {
$data = json_decode($json, true);
print_r($data);
} else {
echo 'Ошибка получения данных';
}
cURL вариант:
$ch = curl_init('https://example.com/data.json');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
echo $response;
} else {
echo 'Ошибка HTTP: ' . $httpCode;
}
Проблемы: allow_url_fopen отключён на хостинге, время ожидания, сертификаты SSL. Решение: использовать cURL с установкой опций timeout, SSL_VERIFYPEER.
Ошибки: не обработаны редиректы, не проверен HTTP-статус.
Цель: получение внешних данных, API-запросы, загрузка файлов по HTTP/HTTPS.
Как получить загруженный пользователем файл (из формы)?
После отправки формы с enctype='multipart/form-data' файл доступен в массиве $_FILES. Для получения его содержимого используйте file_get_contents() из временного расположения.
if (isset($_FILES['uploaded_file']) && $_FILES['uploaded_file']['error'] === UPLOAD_ERR_OK) {
$tmpPath = $_FILES['uploaded_file']['tmp_name'];
$content = file_get_contents($tmpPath);
echo 'Размер: ' . strlen($content) . ' байт';
} else {
echo 'Ошибка загрузки';
}
Проблемы: превышение лимита upload_max_filesize, ошибки при частичной загрузке. Решение: проверять код ошибки и валидировать тип/размер.
Ошибки: отсутствие папки для временных файлов, права на запись.
Цель: обработка файлов, присланных пользователями: изображения, документы и т.д.
Расширенные примеры получения файлов
1. Потоковое чтение большого файла с прогрессом
Пример чтения файла размером 100 МБ блоками по 1 МБ с выводом прогресса.
$filename = 'large_file.bin';
$chunkSize = 1024 * 1024; // 1 MB
$handle = fopen($filename, 'rb');
if ($handle) {
$size = filesize($filename);
$read = 0;
while (!feof($handle)) {
$chunk = fread($handle, $chunkSize);
if ($chunk === false) {
echo 'Ошибка чтения';
break;
}
$read += strlen($chunk);
// Обработка chunk (например, запись в другой файл)
$progress = round($read / $size * 100);
echo "Прочитано $progress%\n";
// Сброс буфера для веб-сценариев
flush();
}
fclose($handle);
} else {
echo 'Не удалось открыть файл';
}
Прочитано 10% Прочитано 20% ... Прочитано 100%
2. Получение удалённого файла с авторизацией и таймаутом
Использование cURL для загрузки защищённого ресурса с Basic HTTP аутентификацией.
$url = 'https://api.example.com/private/report.csv';
$username = 'user';
$password = 'pass';
$timeout = 30;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => "$username:$password",
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/path/to/cacert.pem'
]);
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($httpCode === 200 && $result !== false) {
file_put_contents('report.csv', $result);
echo 'Файл скачан успешно, размер: ' . strlen($result) . ' байт';
} else {
echo 'Ошибка: HTTP ' . $httpCode . ' - ' . $error;
}
Файл скачан успешно, размер: 245678 байт
3. Чтение файла в обратном порядке (последние N строк)
Реализация получения последних 10 строк большого лога без чтения всего файла.
function tail($filename, $lines = 10) {
$handle = fopen($filename, 'r');
if (!$handle) return false;
fseek($handle, 0, SEEK_END);
$pos = ftell($handle);
$data = '';
$count = 0;
while ($pos > 0 && $count < $lines) {
$pos--;
fseek($handle, $pos);
$char = fgetc($handle);
if ($char === "\n" && $pos < ftell($handle) - 1) {
$count++;
}
$data = $char . $data;
}
fclose($handle);
// обрезаем возможный лишний символ в начале
return substr($data, 1);
}
echo tail('error.log', 5);
[2025-03-10 12:00:01] ERROR: DB connection failed [2025-03-10 12:00:02] WARNING: Retry attempt 1 [2025-03-10 12:00:05] ERROR: DB connection failed again [2025-03-10 12:00:10] ERROR: Giving up [2025-03-10 12:00:12] INFO: Service restarted
4. Получение файла через SSH (SFTP) с помощью phpseclib
Для доступа к удалённому файлу по протоколу SFTP используйте библиотеку phpseclib.
require 'vendor/autoload.php';
use phpseclib3\Net\SFTP;
$sftp = new SFTP('192.168.1.100');
if (!$sftp->login('username', 'password')) {
die('Ошибка аутентификации');
}
$remoteFile = '/var/log/application.log';
$content = $sftp->get($remoteFile);
if ($content !== false) {
echo 'Получено ' . strlen($content) . ' байт';
} else {
echo 'Не удалось прочитать файл';
}
Получено 12893 байт
5. Чтение файла с условной распаковкой (gzip)
Если файл сжат gzip, можно прочитать его и распаковать на лету.
$gzFile = 'data.csv.gz';
$handle = gzopen($gzFile, 'r');
if ($handle) {
while (!gzeof($handle)) {
$line = gzgets($handle);
echo $line;
}
gzclose($handle);
} else {
echo 'Ошибка открытия gz-файла';
}
id,name,email 1,Иван,ivan@example.com 2,Петр,petr@example.com