Новая жизнь. Web-студия Татьяны Самойловой.

Web-разработка / [Из песочницы] Загрузка файлов с помощью HTML5 и сколько раз мы сказали нехорошие слова

Опубликовано Янв 26, 2011 в Блог, Новости web


Стояла задача: найти или создать загрузчик файлов на сервер, использующий возможности HTML5 для мультизагрузки. Загрузчик должен:

  • отправлять методом POST любые параметры вместе с файлом;
  • отправлять куки;
  • предоставлять возможность выбора сразу нескольких файлов (или нескольких тысяч – тут как пользователь захочет);
  • отправлять файлы группами;
  • файлы собираются в группы до определенного количества мегабайт, или до определенного количества файлов в группе; (это связано с тем, что на сервере есть ограничение на размер POST запроса и на количество файлов в одном пакете)

Именно по причине отсутствия опыта работы с флешем, для создания загрузчика был выбран только JavaScript.

Итак, что из этого получилось


Сначала был поиск: SWFupload, Uploadify и другие были изучены. Возможно, не слишком хорошо, но каждый из них не удовлетворял всем требованиям.

Баги, баги, баги. Некоторые версии Flash не могут управлять именем переменной. SWFupload не отправляет куки, но у него есть сборщик куков, и он их отправляет только методами GET или POST. Однако у нас CMS на сервере проверяет сессию пользователя именно на основании кук, поэтому Flash был отброшен и было выбрано решение, с использованием HTML5.
Поскольку FileApi поддерживается только FF 3.0+, Chrome и Safari 4+, то разберем тонкости работы с этими браузерами.

Тонкость №1

Получение содержимого файла в Chrome с помощью readAsBinaryString.
При использовании данного метода мы столкнулись с непонятной проблемой, что все файлы приходят битыми, размер которых примерно в 1,5 раза больше изначального размера. Победить эту проблему не получилось, поэтому для хрома ( а так же сафари) мы воспользовались FormData.

Чтобы отправить группу файлов + какие-то данные методом POST в FF (до 4.0) формируем multipart/form-data:
Content-Type: multipart/form-data; boundary=------multipartformboundary1295790618
rn
--------multipartformboundary1295790618
rn
Content-Disposition: form-data; name='user_files[]';filename='My_File1.jpg'
rn
Content-Type: application/octet-stream
rn
rn
содержимое файла
rn
--------multipartformboundary1295790618
rn
Content-Disposition: form-data; name='user_files[]';filename='My_File2.jpg'
rn
Content-Type: application/octet-stream
rn
rn
содержимое файла
rn
--------multipartformboundary1295790618
rn
Content-Disposition: form-data; name='my_param'
rn
rn
Param_value
rn
--------multipartformboundary1295790618
rn
Content-Disposition: form-data; name='my_param'
rn
rn
Param_value
rn
--------multipartformboundary1295790618--
rn

Тонкость №2

Определение поддержки FormData можно проверять следующим образом:
function isFormDataSupported() {
return (window.FormData);
}

Тонкость №3

В FF 3.0/3.5 и FF 3.6 используются разные функции для получения содержимого файлов:
FF 3.0/3.5: readAsBinary()
FF 3.6: getAsBinary()

Тонкость №4

Также есть разница в отправке файлов через XMLHttpRequest:
для FormData нужно отправлять методом send(), а для отправки файлов, полученных методом getAsBinary() необходимо отправлять методом sendAsBinary().

Тонкость №5

FF редко вызывает событие progress у XMLHttpRequest, в отличии от хрома или Сафари. На деле у FF событие progress вообще иногда не отрабатывало при очень быстром соединении или на локалхосте.

Тонкость №6

При событии abort у XMLHttpRequest в FF также вызывается событие error. С этим нужно быть особо внимательным, если у вас там стоит обработчик на ошибки — это может вызвать дополнительные вопросы у пользователя.

Тонкость №7

Если вы используете FormData, то отправляйте методом send(). Иначе — sendAsBinary().

Для PHP советую обратить внимание на следующие настройки в php.ini:

post_max_size — максимальный размер POST.
upload_max_filesize — максимальный размер файла.
max_file_uploads — максимальное количество загружаемых файлов.

Если будете использовать наш скрипт, не забудьте изменить скрипт под настройки своего сервера.

Читатели рекомендуют прочесть:



Оставить комментарий