Как должна выглядеть HTML-форма закачки файла?
- На экране — красивая, кастомизированная кнопка «Закачать файл».
- После её нажатия появляется системное окно выбора файла.
- Пользователь выбирает файл и закачка автоматически начинается.
- Во время закачки под кнопкой отображается прогресс-бар, с процентами и визуальными делениями.
- По завершению закачки — сообщение «файл закачен».
Головная боль #1
HTML-поле с выбором файла кастомизировать невозможно. Назначить визуальные CSS-свойства нельзя. Это такое техническое ограничение, оно существовало всегда (более 10 лет уже), и для изменения такого положения сделать тоже ничего невозможно. HTML-код для поля: `<input type="file" name="myfile">`.
В Firefox отсутствует поддержка метода `.click()` поэтому невозможно вызвать окно выбора файла по нажатию на произвольный элемент.
Головная боль #2
При автоматическом старте закачки отменить действие нельзя. Разве что закрыть браузер и потерять страницу, с которой закачивался файл. А если это было AJAX-приложение, то придётся заново проходить все этапы, предшествующие закачке файла.
О докачке файла вообще говорить не приходится. Ведь браузер не предназначен для управления файлами. Так думают почти все веб-разработчики, да и разработчики самих браузеров, но только не пользователи, которым некогда познавать основы работы с ftp.
Головная боль #3
Сделать прогресс-бар стандартными средствами без установки плагинов в браузер, на сервер, в том числе без Flash — никак нельзя.
Если бы можно было узнать системное имя закачиваемого файла до начала закачки, тогда можно было бы обновлять прогресс-бар AJAX-запросами. Но в PHP имя файла становится известным после закачки (переменная `$_FILES`).
Головная боль #4
Осуществить загрузку файла способом (объект XMLHttpRequest, сокращенно XHR), который стал своего рода стандартом, без перезагрузки страницы — невозможно. Но есть другие способы:
- с помощью методов ADODB (только для IE);
- с помощью методов [@mozilla] (только для Firefox);
- с помощью W3C File API (только для Firefox 3.6+, Chrome, Safari и только частично);
- c применением страшного, ужасного и опасного тега `<iframe>`;
- с куда более страшным и дырявым Flash'ем.
Ни одного нормального метода!
Головная боль #5
Всё это должно работать кроссбраузерно — в как можно большем числе современных и не очень браузеров.
Есть ли лекарство?
Учитывая множество вариантов и кривизну их реализации в браузерах, наиболее подходящим, компромиссным методом является загрузка файла через динамически создаваемый iframe. Это ни разу не AJAX, но тоже «без перезагрузки страницы».
Засада с iframe есть только у Internet Explorer — скрипт, передающий данные в iframe (как правило, это JSON-данные) должен сообщать неправильный MIME-тип: `text/html`. Иначе IE будет предлагать сохранить файл.
Красивую, «нормальную» кнопку сделать можно, но очень хитрым способом, требующим смекалки и поддержки CSS-свойства `.opacity` со стороны браузера в любом виде, будь то `.style.filter`.
Если кратко — поле `input type="file"` с помощью CSS делается прозрачным и растягивается на всю область «нормальной» кнопки. При наведении курсора на «нормальную» кнопку, прозрачное поле подставляется под курсор, пользователь кликает будто бы на кнопку, а на самом деле на HTML-поле, тем самым вызывая системное окно выбора файла.