Обработка множественных файлов средствами PHP
Основные подходы к работе с несколькими файлами
Эффективное решение: отправка массива файлов через HTML форму
Для загрузки нескольких файлов одновременно используется HTML форма с атрибутом enctype="multipart/form-data" и полем ввода типа file с именем, заканчивающимся на квадратные скобки name="files[]". Это позволяет PHP воспринимать все загруженные файлы как массив в суперглобальном массиве $_FILES.
<form method="POST" action="upload.php" enctype="multipart/form-data">
<input type="file" name="files[]" multiple>
<button type="submit">Загрузить</button>
</form>
Php get extension (получение информации о файлах в php)
В PHP обработка выглядит так:
$uploadDir = 'uploads/';
if (!empty($_FILES['files']['name'][0])) {
foreach ($_FILES['files']['name'] as $key => $name) {
$tmpName = $_FILES['files']['tmp_name'][$key];
$error = $_FILES['files']['error'][$key];
if ($error === UPLOAD_ERR_OK) {
$dest = $uploadDir . basename($name);
if (move_uploaded_file($tmpName, $dest)) {
echo "Файл $name загружен успешно.";
}
}
}
}
Php корневой каталог (корневой каталог сайта в php)
Данный подход позволяет обрабатывать неограниченное количество файлов, передаваемых браузером. Атрибут multiple у элемента <input> даёт возможность выбрать несколько файлов в диалоговом окне.
Когда это применяется
- Галереи изображений
- Массовая загрузка документов
- Формы обратной связи с возможностью прикрепления нескольких файлов
Как загрузить несколько файлов через отдельные поля ввода?
Иногда требуется задать фиксированное количество полей для загрузки, например, 3 файла. В этом случае каждое поле получает уникальное имя:
<input type="file" name="file1">
<input type="file" name="file2">
<input type="file" name="file3">
Php база в файле (хранение данных в файлах в php (flat-file database))
Обработчик должен проверять каждое поле отдельно:
for ($i = 1; $i <= 3; $i++) {
$field = 'file'.$i;
if (!empty($_FILES[$field]['name'])) {
// обработка
}
}
Php include server (include сервера php)
Такой способ используется, когда количество файлов строго определено и заранее известно.
Возможные проблемы:
- Ограничение максимального размера запроса в php.ini (
post_max_size,upload_max_filesize). При загрузке больших файлов может возникнуть ошибка. Решение: увеличить соответствующие директивы. - Превышение времени выполнения скрипта. Для обработки множества файлов следует установить
set_time_limit(0)или увеличить лимит. - Конфликт имен файлов. Пользователь может загрузить файлы с одинаковыми именами. Рекомендуется использовать уникальные имена, например, с добавлением временной метки или случайной строки.
Как обработать несколько файлов, переданных через массив с другими структурами (например, массив массивов)?
Структура $_FILES не всегда удобна. Альтернативой является реорганизация массива в плоскую структуру. Для этого используется функция для перегруппировки:
function reorganizeFiles($filePost) {
$files = [];
foreach ($filePost as $key => $all) {
foreach ($all as $i => $val) {
$files[$i][$key] = $val;
}
}
return $files;
}
$files = reorganizeFiles($_FILES['files']);
Php несколько файлов (несколько файлов в php)
Теперь каждый элемент $files[$i] содержит обычный набор полей (name, tmp_name и т.д.). Это упрощает перебор.
Как осуществить загрузку нескольких файлов с использованием cURL и PHP?
Для отправки нескольких файлов на другой сервер используется библиотека cURL. Формируется массив с ключами в стиле files[0]:
$ch = curl_init();
$post = [
'files[0]' => new CURLFile('/path/to/file1.txt'),
'files[1]' => new CURLFile('/path/to/file2.jpg')
];
curl_setopt($ch, CURLOPT_URL, 'http://example.com/upload.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_exec($ch);
Php файл с сервера (файл с сервера php)
На принимающей стороне файлы будут доступны так же, как при обычной форме.
Как прочитать содержимое нескольких файлов одновременно (без загрузки через форму)?
Иногда требуется обработать уже существующие на сервере файлы. Для этого используется функция glob() или scandir().
$files = glob('data/*.txt');
foreach ($files as $file) {
$content = file_get_contents($file);
echo "Содержимое $file: $content";
}
Этот подход удобен для пакетной обработки логов или экспорта данных.
Типичные ошибки:
- Отсутствие прав на чтение/запись директорий. Следует проверять
is_readable()иis_writable(). - Игнорирование символических ссылок. Функция
is_file()поможет отличить файлы от ссылок.
Расширенные примеры работы с несколькими файлами
Пример 1: Загрузка файлов с проверкой MIME-типа и размера
Валидация каждого файла по типу (только изображения) и максимальному размеру (5 МБ). В случае ошибки формируется массив с сообщениями.
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 5 * 1024 * 1024; // 5 MB
$errors = [];
$uploadDir = 'uploads/';
foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
if ($_FILES['files']['error'][$key] !== UPLOAD_ERR_OK) {
$errors[] = "Ошибка загрузки файла {$_FILES['files']['name'][$key]}";
continue;
}
if ($_FILES['files']['size'][$key] > $maxSize) {
$errors[] = "Файл {$_FILES['files']['name'][$key]} превышает 5 МБ";
continue;
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmpName);
finfo_close($finfo);
if (!in_array($mime, $allowedTypes)) {
$errors[] = "Тип файла {$_FILES['files']['name'][$key]} не разрешен";
continue;
}
$ext = pathinfo($_FILES['files']['name'][$key], PATHINFO_EXTENSION);
$newName = uniqid() . '.' . $ext;
if (move_uploaded_file($tmpName, $uploadDir . $newName)) {
echo "Файл {$_FILES['files']['name'][$key]} сохранён как $newName<br>";
}
}
if (!empty($errors)) {
echo implode('<br>', $errors);
}
Результат (пример вывода):
Файл photo1.jpg сохранён как 67a12b3c4d5e6.jpg Файл photo2.png сохранён как 67a12b3c4d5e7.png Тип файла document.pdf не разрешен
Пример 2: Асинхронная загрузка нескольких файлов через AJAX с отображением прогресса
На стороне клиента используется XMLHttpRequest с отслеживанием прогресса загрузки каждого файла. На сервере файлы обрабатываются стандартным способом. Для удобства файлы передаются в виде массива.
// JavaScript (упрощённо)
let formData = new FormData();
let files = document.getElementById('fileInput').files;
for (let i = 0; i < files.length; i++) {
formData.append('files[]', files[i]);
}
let xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
let percent = Math.round((e.loaded / e.total) * 100);
console.log('Общий прогресс: ' + percent + '%');
}
});
xhr.open('POST', 'upload.php', true);
xhr.send(formData);
Серверная часть (upload.php) может возвращать JSON с результатами:
$response = [];
foreach ($_FILES['files']['name'] as $key => $name) {
// ... обработка как в примере 1 ...
$response[] = ['name' => $name, 'status' => 'success'];
}
echo json_encode($response);
Пример 3: Пакетное переименование и перемещение файлов с использованием итератора
$sourceDir = '/var/www/incoming';
$destDir = '/var/www/processed';
$it = new DirectoryIterator($sourceDir);
foreach ($it as $fileInfo) {
if ($fileInfo->isFile()) {
$newName = 'processed_' . $fileInfo->getFilename();
rename($fileInfo->getPathname(), $destDir . '/' . $newName);
}
}
Результат: все файлы из папки incoming получают префикс processed_ и перемещаются в processed.
Пример 4: Загрузка ZIP-архива и его распаковка на сервере
if ($_FILES['archive']['error'] === UPLOAD_ERR_OK) {
$zip = new ZipArchive();
if ($zip->open($_FILES['archive']['tmp_name']) === TRUE) {
$zip->extractTo('extracted/');
$zip->close();
echo 'Архив распакован.';
} else {
echo 'Не удалось открыть архив.';
}
}
Перед распаковкой следует проверять структуру архива на предмет вредоносных файлов.