Как увеличить максимальный размер загружаемого файла в PHP?
Почему возникает проблема и как её решить
Вы столкнулись с классической проблемой — ограничением PHP на размер загружаемых файлов. По умолчанию PHP разрешает загрузку файлов не более 2 МБ (значение upload_max_filesize). Когда вы пытаетесь загрузить файл большего размера, PHP молча его отклоняет, не вызывая ошибку в коде (если вы её не проверяете).
Чтобы увеличить лимит, нужно изменить несколько директив в файле php.ini. Вот полный список параметров, которые влияют на загрузку файлов:
; Максимальный размер одного загружаемого файла
upload_max_filesize = 20M
; Максимальный общий размер всех файлов в одном запросе
post_max_size = 25M
; Максимальное время выполнения скрипта (в секундах)
max_execution_time = 300
; Максимальное время на получение данных (в секундах)
max_input_time = 300
; Объём памяти, доступный скрипту
memory_limit = 128M
Важно: post_max_size должен быть больше, чем upload_max_filesize, иначе даже один большой файл не пройдёт. Обычно делают на 5-10 МБ больше.
Где найти php.ini и как применить изменения
- Найдите файл php.ini на вашем сервере. Чаще всего он лежит в корневой директории PHP или в папке
/etc/php/(на Linux). - Откройте его в текстовом редакторе с правами администратора.
- Найдите указанные выше директивы (можно использовать поиск по слову "upload").
- Измените значения на нужные вам.
- Сохраните файл и перезапустите веб-сервер (Apache, Nginx или PHP-FPM).
Проверка ошибок в коде
Даже после изменения настроек, всегда проверяйте код ошибки загрузки. Добавьте в ваш обработчик проверку массива $_FILES['file']['error']:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["file"]["name"]);
// Проверяем код ошибки
if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
$error_messages = [
UPLOAD_ERR_INI_SIZE => 'Размер файла превышает лимит upload_max_filesize в php.ini',
UPLOAD_ERR_FORM_SIZE => 'Размер файла превышает лимит MAX_FILE_SIZE в HTML-форме',
UPLOAD_ERR_PARTIAL => 'Файл был загружен только частично',
UPLOAD_ERR_NO_FILE => 'Файл не был загружен',
UPLOAD_ERR_NO_TMP_DIR => 'Отсутствует временная папка для загрузки',
UPLOAD_ERR_CANT_WRITE => 'Не удалось записать файл на диск',
];
$error_code = $_FILES['file']['error'];
$message = $error_messages[$error_code] ?? 'Неизвестная ошибка';
die("Ошибка загрузки: $message");
}
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
echo "Файл загружен: " . htmlspecialchars(basename($_FILES["file"]["name"]));
} else {
echo "Ошибка при перемещении файла.";
}
}
?>
Если нет доступа к php.ini (хостинг)
На общих хостингах вы можете не иметь доступа к основному php.ini. В этом случае попробуйте:
- Создать файл
.user.iniв корневой папке сайта и прописать те же директивы. - Или добавить в файл
.htaccess(Apache):
php_value upload_max_filesize 20M
php_value post_max_size 25M
php_value max_execution_time 300
После всех изменений проверьте текущие настройки с помощью phpinfo() — создайте временный PHP-файл с этим кодом и откройте его в браузере. Найдите секцию "Core" и посмотрите значения upload_max_filesize и post_max_size.
Альтернативный подход: загрузка файлов по частям
Если вы не можете изменить настройки сервера (например, на виртуальном хостинге с жёсткими ограничениями), можно реализовать загрузку файлов по частям на клиентской стороне с помощью JavaScript (например, через библиотеку FilePond или Dropzone.js).
Вот минимальный пример с использованием нативного JavaScript и серверной части на PHP:
// JavaScript — разбиваем файл на части по 1 МБ
const chunkSize = 1 * 1024 * 1024; // 1 MB
const file = document.getElementById('fileInput').files[0];
let start = 0;
while (start < file.size) {
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
const formData = new FormData();
formData.append('file', chunk);
formData.append('fileName', file.name);
formData.append('offset', start);
fetch('upload_chunk.php', { method: 'POST', body: formData });
start = end;
}
// PHP — склеиваем части
<?php
$fileName = $_POST['fileName'];
$offset = (int)$_POST['offset'];
$chunk = file_get_contents($_FILES['file']['tmp_name']);
$fileHandle = fopen('uploads/' . $fileName, 'ab');
fseek($fileHandle, $offset);
fwrite($fileHandle, $chunk);
fclose($fileHandle);
echo "OK";
?>
Этот метод обходит ограничения сервера, так как каждый отдельный кусок файла имеет размер 1 МБ и проходит под лимитом upload_max_filesize. Однако он сложнее в реализации и требует поддержки на клиентской стороне. Для небольших проектов проще всё же договориться с хостингом об увеличении лимитов.