Например: Программист
76,0
рейтинг
19 сентября 2014 в 16:58

Разработка → Вы не можете закачать файлы на сервер в мобильном Safari 8.0 перевод

Печально, но факт. Новая версия iOS содержит баг, который делает невозможным отправку любых файлов на сервер из браузера. Когда вы выбираете файл в любой форме на HTML странице и пытатесь его отправить, браузер посылает запрос без файла. Он показывает, что ждет ответа на запрос, но на самом деле ответ не приходит.

Более того, баг касается не только HTML-форм. Если вы отправляете файл из Javascript, конструируя объект FormData (часть API XMLHttpRequest Level 2), это приводит к тому же результату. И даже если вы делаете то же самое из нативного приложения, которое является оберткой над HTML-браузером (например, Apache Cordova), то получаете такой же результат.

Почему же не приходит ответ. Если бы файл просто не отсылался, мы могли бы ожидать, что на сервер приходил бы пустой файл или сервер возвращал бы ошибку, что форма отправлена без файла. Однако сервер просто не шлет никакого ответа (даже 400 bad request) и не закрывает соединение. Все дело в том, какой именно запрос шлет Safari.

POST /form/ HTTP/1.1
Host: 192.168.5.59:8000
Referer: http://192.168.5.59:8000/
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryGVP84V9BXQSqpZw2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Content-Length: 134573
Accept-Language: ru
Origin: http://192.168.5.59:8000
Accept-Encoding: gzip, deflate
Connection: keep-alive
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4

------WebKitFormBoundaryGVP84V9BXQSqpZw2
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryGVP84V9BXQSqpZw2--

Из заголовков видно, что запрос с отправкой файла должен иметь длину 134573 байта (заголовок Content-Length), а на самом деле в теле запроса отсутствует тело файла, из-за чего реальная длина запроса составляет 176 байт. В результате сервер ждет, когда браузер пошлет недостающие 134397 байт, а браузер думает, что он послал уже весь запрос и ждет ответа от сервера. Ни того ни другого не произойдет никогда и соединение просто закрывается по таймауту.

Баг проявляется в Safari 8.0 (билд 600.1.4) под iOS 8.0 (билд 12A365). Что интересно, под симулятором iOS, который идет в комплекте с XCode, данный баг не проявляется, хотя номера билдов там такие же. Однако на реальных устройствах (были проверены iPhone 4S, iPhone 5, iPad 3) баг воспроизводится всегда. Мы надеемся, что баг будет исправлен уже в ближайшем минорном обновлении.

Если кто-то хочет увидеть ошибку сам или попробовать другие девайсы.

Дебагер в Сафари тут бесполезен, потому что в любом случае показывает тело запроса без содержимого файлов. Т.к. ошибка непосредственно в работе с HTTP, сделать онлайн-пример достаточно сложно. Ничего умнее не придумал, чем запустить netcat и слать запросы на него. Вот инструкция:

1) Запускаете netcat -l 8000 на компе в одной wi-fi сетке с устройством.
2) Делаете простейшую форму на jsbin или jsfiddle:
<form action="http://192.168.5.59:8000/form/" method="post" enctype="multipart/form-data">
  <input type="file" name="file">
  <input type="submit">
</form>

Где 192.168.5.59 — ip адрес компа, где запущен netcat.

3) Открываете сделанный bin или fiddle на устройстве. Выбираете любой файл, шлете.
4) Смотрите на вывод netcat.

Если ответ похож на тот, что в статье, то баг присутствует. Если перед последней строчкой есть содержимое файла, то нет.
Перевод: Uploadcare
Александр Карпинский @homm
карма
89,5
рейтинг 76,0
Например: Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (19)

  • 0
    В бетах загрузка работала?
    • 0
      Я не знаю, не ставил беты на живые устройства. В статье дописал, как можно проверить, если у кого-то еще осталась бета.
    • 0
      Не работала, в том числе и на последнем GM. Так что многие успели подготовиться и держали нужные патчи на готове.
      • +2
        Какие патчи тут можно сделать? Единственное, что приходит в голову — спрятать инпут, извиниться перед пользователем.
        • +1
          Это и имел ввиду. Запретить аплоад лучше, чем давать ложную надежду.
  • +1
    Так же перестало работать в новом Safari подключение к внутрекорпоративной информационной системе с любых устройств с iOS 8 по протоколу HTTPS.
  • 0
    А ещё только Safari на iOS может скачивать файлы любого расширения, другие браузеры не хотят…
    • 0
      А куда он их скачает? В фотографии?
      • +1
        Просто качает, а потом предлагает открыть в приложении, заявившем о поддержке данных расширений.
  • +2
    Вот ещё баг с аплоадом github.com/Widen/fine-uploader/issues/1283. И он уже совсем печальный :(
  • 0
    Это баг, это починят, это не страшно, но они полностью выпилили minimal-ui для вьюпорта. Цензурных слов на них нет.
    • 0
      зато фокус на инпутах можно самостоятельно ставить
  • +2
    Занимательный факт – всё отлично работает в iOS Simulator. Ещё когда была бета надеялся, что пофиксят в релизе. Но нет.
    • +2
      Вообще лучше не надеятся, а репортить баги. Возможно, мне просто повезло, но почти все, что я зарепортил было починено, включая крэш сафари на какой-то левой страничке
  • +4
    У меня вот в восьмёрке будильник после снуза не звенит больше — это поопаснее :)
  • 0
    Такой ощутимый функционал, «лежащий на поверхности», и не проверен. Куда смотрел их отдел тестирования? Да и сами разработчики неужели не пробуют за время разработки хоть раз файл залить…
  • 0
    Сыровая у них в этот раз прошивка получилась, суда по комментариям. Торопились, наверное, просто.

    P.S. Старое правило ставить новую ОСь хотя бы после выпуска SP к ней все еще имеет право на существование.
  • 0
    Только что проверил, в Chrome под iOS 8 картинки загружаются, в Safari — нет.
    • 0
      Выкатили 8.0.2, исправили там баг с загрузкой. Сегодня проверял — всё работает, наконец.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.