Загрузка произвольного количества файлов на сервер
PHP, javascript, Дележка опытом, Разработка 06.02.2008Что я подразумеваю под загрузкой произвольного количества: пользователь выбирает сколько угодно файлов, нажимает кнопку “загрузить” и файлы загружаются на сервер и обрабатываются. Новые поля для выбора файлов создаются динамически.
Шаг 1: Создаём форму
<form method=”POST” id=”upform” name=”upform” enctype=”multipart/form-data”>
<input type=”file” size=”50″ onchange=”addElement()” name=”first”>
</form><input type=”button” value=”Загрузить” onclick=”upform.submit()”>
На форме у нас всего один элемент для загрузки файлов под именем first и назначено событие на изменение(выбор) файла - addElement(). Кнопка загрузить стоит отдельно от формы, почему сделано именно так будет объяснено далее.
Шаг 2: Создаем javascript функцию динамического добавления нового поля для файла
<script>
function addElement() {
var uf = document.getElementById(’upform’);// Создаём новое поле для выбора файла
var newFile = document.createElement(’input’);var fileIdName = ‘myFile’+Math.random(); //Случайное имя
newFile.setAttribute(’id’,fileIdName);
newFile.setAttribute(’name’,fileIdName);
newFile.setAttribute(’type’,'file’);
newFile.setAttribute(’size’,'50′);// при выборе файла данное поле тоже должно добавлять еще одно поле
newFile.setAttribute(’onChange’,'addElement()’);
newFile.onchange = addElement;uf.appendChild(newFile); // добавляем поле к форме, поле добавится в конец формы, потому мы ранее
// и вынесли кнопку “загрузить” за форму - логичнее она будет смотреться в конце
}
</script>
Шаг 3: Обработка загруженных файлов на сервере
Для обработки файлов на сервере вставляем следующий код:
foreach ($_FILES as $file) {
// здесь стандартная обработка загруженных файлов, примеров в интернете полно
// также здесь можно проверять, например, что это динамически добавлненное поле (у нас оно начинается с “myFile”)}
Рабочий пример можно посмотреть здесь (в примере опущено enctype=”multipart/form-data”).
Код написан для админки одного из сайтов фирмы Бош, он не идеален (например если два раза выбрать файл в первом поле, то будет два пустых поля), но это не сложно добавить самим
Гарантированно работает в Firefox, IE, Opera. Удачного кодинга!
UPDATE: по просьбе выкладываю серверную часть загрузки файлов
Шаг 3.1: Обработка загруженных файлов на сервере (код)
Вот приблизительный код(урезанный), который я использую. Имейте в виду что код используется строго в админке, по этому в паблик доступе с безопасностью могут быть проблемы
$upload_path = $_SERVER[’DOCUMENT_ROOT’].”/uploads”;
$valid_types = array(
“pdf”, ‘doc’, ‘txt’, ‘jpg’,'xls’,'gif’,'png’,'zip’,'rar’
);
$max_file_size = “10000000″;if (sizeof($_FILES)>0) {
$errors = array();foreach ($_FILES as $file) {
if (strlen($file[”name”])<=0)
continue;
if (is_uploaded_file($file[’tmp_name’])) {
$filename = $file[’tmp_name’];
$ext = substr($file[’name’], 1 + strrpos($file[’name’], “.”));
$ext = strtolower($ext);
$name = $file[’name’];
if (file_exists($upload_path.$name)) {
$errors[$name] = “\nТакой файл уже существует”;
} elseif (filesize($filename) > $max_file_size) {
$errors[$name] = “\nРазмер файла больше 10 мегабайт”;
} elseif (!in_array($ext, $valid_types)) {
$errors[$name] = “\nНе верный тип файла. “;
} else {
$size =$file[’size’];
if (@move_uploaded_file($filename, $upload_path.$name)) {
// Здесь запись в базу, если необходимо
} else {
$errors[$name] = “\nОшибка перемещения файла. “;
}}
} else {
$errors[$name] = “\nНеобходимо выбрать правильный файл.”;
}
}
}
Небольшие комментарии:
- в $errors падают ошибки загрузки файлов
- в коде проверяются ТОЛЬКО расширения по списку ($valid_types), но не реальныйтип файла
- и да - 10 мегабайт, не 10000000 байт, я в курсе
Похожие записи:
- No related posts
Интересно почитать:
- Загрузка произвольного количества файлов на сервер
- Akismet - какаха
- Анти-спам защита Wordpress: не опять, а снова


(4 голосов, средний бал: 4.75 из 5) 

08.02.2008 в 11:10
а как по поводу загрузки нескольких файлов, общий размер которых больше максимального буфера, установленном в настройках пых-пыха?
08.02.2008 в 12:34
Подобное не предусматривалось, да и задача подобная не ставилась, как ты догадался
Эт админка
08.02.2008 в 14:07
пасиба
легко и просто 
09.02.2008 в 09:32
Спасибо. Попробую осилить…
10.02.2008 в 17:34
Нехорошо генерировать имя при помощи Math.random(). Есть вероятность, что сгенерируется имя, которое уже есть. Неплохо бы проверять, есть ли такое имя уже или нет. Для этого, можно присваивать элементу не только name с рандомом, но и такой же id. И делать как-то так:
var rand = Math.random();
if(!document.getElementById('myFile'+rand)){
var fileIdName = ‘myFile’+rand;
}
Или можно просто давать имена по порядку. Тогда нужна глобальная переменная, которая будет помнить какой номер был последним. Так надежней.
Ну и потом, ИМХО, зря вы не расписали код загрузки файлов на сервере. При загрузке нескольких файлов сразу, код будет другим, нежели при загрузке одного файла.
11.02.2008 в 12:09
Я сделал бы так:
А потом foreach пробежать по массиву. И не надо генерить рендомно имя новое полю.
11.02.2008 в 12:10
input type=”file” size=”50″ onchange=”addElement()” name=”first[]”
11.02.2008 в 12:18
SHAman: Да, ты прав, я думал об этом (про уникальность имен)
Сделал небольшой апдейт с кодом обработки на сервере
SoccerfanХм… а идея
Хотя если нужно для каких-нибудь целей еще и id, то не покатит… А так то вполне реально
11.02.2008 в 12:26
можно ID добавлять hidden полем аналогично
input type=”hidden” name=”id[]” вместе с добавлением input type=”file” size=”50″ onchange=”addElement()” name=”first[]”
Тогда, например, id[4] будет соответствовать загружаемому файлу first[4].
11.02.2008 в 12:42
Нет, я имел в виду обработку на клиентской стороне с помощью javascript, где id должны быть уникальными.
12.02.2008 в 17:58
foreach замедляет работу в 9-10 раз по сравнению с for.
12.02.2008 в 19:51
Ну мне foreach роднее
Да и скорость зависит от ситуации, иногда и foreach впереди.
13.02.2008 в 09:32
Спасибо, было интересно прочитать ^^
26.02.2008 в 09:18
Петрович, в юниксах есть вызов, помойму tmpname называется, точно не помню - спроси гугл, который возвращает случайное не существующее имя файла, у php есть к нему враппер. не надо изобретать велосипеды
26.02.2008 в 10:02
Вов, речь не о том шла
Смысл не как сохранить все файлы с уникальными именами, а именно клиентская сторона и процесс загрузки.
26.02.2008 в 10:15
если уж на это пошло, то делать как через tmpname, так и тобой предложенным методом - это потенциальная дырка для безопасности. если злой хацкер наперёд угадает имя файла, куда ты собираешься записать (а сделать это можно запросто), он делает симлинк на файл, который ты сам для него перезапишешь с правами апача. есть специальный вызов (не помню его название а искать лень) который делает атомарную операцию - генерит случайное имя и тут же создаёт этот файл для тебя. не знаю правда будет ли это в винде работать.
04.05.2008 в 14:17
2vovan
Напиши, плиз, код файла-обработчика формы для любого количества загруженных файлов, а не для одного,
потому что мой мозг не может придумать ничего путевого.
Зарание благодарю.
05.05.2008 в 12:04
сникерс, тренируй лучше свой мозг, Вована бесплатно не купишь.
05.05.2008 в 12:15
sNICkers, читай внимательнее
после UPDATE как раз и написан код для обработки N-ного количества загруженных файлов