Последнюю ситуацию можно улучшить, если использовать встроенную в браузеры возможность множественной загрузки файлов. Из всех браузеров сейчас данную возможность не поддерживает только Internet Explorer (впрочем, мы ещё не видели девятую версию, может там что-то изменится), остальные браузеры — Opera 9 и выше (а так же версии 3.5—6.05), Firefox 3.6+, Chrome 3.0.191.0+ и Safari 4.0.1+ такую возможность предоставляют.
Достаточно написать что-то вроде
Copy Source | Copy HTML
- <form enctype="multipart/form-data" method="post">
- <input type="file" min="1" max="9999" name="file[]" multiple="true" />
- <input type="submit" name="submit" />
- form>
PHP оказался готов к такой конструкции (именно для него в параметре «name» стоят квадратные скобки), он просто разложит загружаемые файлы по элементам массива $_FILES, если только мы не используем «Оперу».
К сожалению, «Опера» (ещё с версии 3.5) отправляет, в этом случае, запрос в формате «multipart/mixed», который PHP не понимает.
Я попробовал исправить эту ситуацию.
К счастью для нас, PHP, приняв такой запрос, поместит его содержимое в массив $_POST (в данном случае он попадёт в $_POST[`file`][0], дальше остаётся только распарсить его и переложить в $_FILES (надеюсь, директива magic_quotes_gpc у вас отключена).
В качестве парсера я использовал PECL-модуль mailparse (есть бинарник для Windows).
У меня в примере ожидается параметр «file», но это значение легко вынести в настройку. Код мне кажется достаточно простым, чтобы его не комментировать, но, если что-то не понятно, спросите, я добавлю комментарии.
Copy Source | Copy HTML
- if (isset($_POST[`file`], $_POST[`file`][ 0])) {
-
- if ($idx = strpos($_POST[`file`][ 0], "n")) {
- $bound = substr($_POST[`file`][ 0], 2, $idx-2);
-
- $body = "MIME-Version: 1.0\nContent-type: multipart/form-data; boundary={$bound}\n\n".
- $_POST[`file`][ 0];
-
- unset($_POST[`file`][ 0]);
- $f = &$_FILES[`file`];
-
- $f[`name`] = $f[`type`] = $f[`tmp_name`] = $f[`error`] = $f[`size`];
-
- $msg = mailparse_msg_create();
-
- if (mailparse_msg_parse($msg, $body)) {
- $i = 0;
-
- foreach(mailparse_msg_get_structure($msg) as $st) {
-
- $section = mailparse_msg_get_part($msg, $st);
-
- $data = mailparse_msg_get_part_data($section);
-
- if ($data[`content-type`] == `multipart/form-data`) {
- continue;
- }
-
- ob_start();
- if (mailparse_msg_extract_part($section, $body)) {
- $tmp = tempnam(sys_get_temp_dir(), `php`);
- file_put_contents($tmp, ob_get_clean());
-
- $f[`name`][$i] = $data[`disposition-filename`];
- $f[`type`][$i] = $data[`content-type`];
- $f[`tmp_name`][$i] = $tmp;
- $f[`error`][$i] = 0;
- $f[`size`][$i] = filesize($tmp);
-
- $i++;
- } else {
- ob_end_clean();
- }
- }
- }
- unset($f);
-
- mailparse_msg_free($msg);
- }
- }