Каковы методы, чтобы обойти правила безопасности загрузки файлов IE?

Internet Explorer (с настройками по умолчанию, который, как я обычно предполагаю, будет действовать на рабочих столах Great Unwashed), кажется, не нравится идея принятия содержимого вложения в ответе HTTP, если соответствующий запрос не был сделан непосредственно из действие пользователя (например, обработчик "click" или подчиненная форма submit). Есть, вероятно, больше деталей и нюансов, но это основное поведение, которое расстраивает меня.

Мне кажется, что эта ситуация распространена: пользовательский интерфейс перед некоторым загружаемым контентом -— скажем, подготовленный отчет в формате PDF — позволяет использовать некоторые параметры и входы для создания контента. Теперь, как и во всех формах, которые позволяют пользователю определять, как приложение что-то делает, возможно, что вход будет ошибочным. Не всегда, но иногда.

Таким образом, существует дилемма. Если клиент пытается сделать что-то необычное, например, выполнить транзакцию AJAX, чтобы сервер проверил содержимое формы, а затем повторно отправить для загрузки, IE не понравится. Это не понравится, потому что фактическая транзакция HTTP, которая несет вложение назад, произойдет не в исходном обработчике событий пользовательского действия, а в обратном вызове завершения AJAX. Хуже того, поскольку панель безопасности IE, похоже, считает, что решение всех проблем состоит в том, чтобы просто перезагрузить внешнюю страницу с ее исходного URL-адреса, ее приглашение пользователю продолжить и загрузить подозрительный контент даже не будет работать.

Другой вариант - просто удалить форму. Сервер проверяет параметры, и если что-то не так, он отвечает на страницу формы-контейнера, соответствующим образом надуваясь сообщениями об ошибках. Если содержимое формы в порядке, оно генерирует контент и отправляет его обратно в ответе HTTP в виде прикрепленного файла. В этом случае (я думаю), IE счастлив, потому что контент, по-видимому, напрямую запрашивался пользователем (что, кстати, смехотворно хмурый способ рассказать хороший контент из плохого контента). Это замечательно, но теперь проблема заключается в том, что клиентская среда (то есть код на моей странице) не может сказать, что загрузка работала, поэтому форма все еще просто сидит там. Если моя форма находится в каком-то диалоге, мне действительно нужно закрыть это, когда операция завершена — действительно, что одна из мотиваций для этого - путь AJAX.

Мне кажется, что единственное, что нужно сделать, это оснастить диалоговые окна формы сообщениями, которые говорят что-то вроде: "Закройте это, когда начнется загрузка". Это действительно кажется мне хромым, потому что это пример интерфейса "пожалуйста, нажмите эту кнопку для меня": в идеале мой собственный код должен быть способен нажимать кнопку "buutton", когда это уместно. Ключевая вещь, которую я не знаю, заключается в том, есть ли способ для кода клиента обнаружить, что представление формы привело к загрузке приложения. Я никогда не слышал о том, как это обнаружить, но это нарушит тупик для меня.

Ответ 1

Я так понимаю, вы отправляете форму с другим целевым окном; следовательно, форма остается на месте.

Существует несколько вариантов.

  • Отключите кнопку отправки и выполните текущую проверку в фоновом режиме, опросив форму для внесения изменений в поля и затем отменив запрос проверки для поля при его изменении. Когда форма находится в правильном состоянии, включите кнопку; когда это не так, отключите кнопку. Это не идеально, так как будет иметь место задержка, но она может быть достаточно хороша для того, что вы делаете.
  • Проведите базовую проверку, которая не требует округления к серверу в обработчике события формы submit, затем отправьте форму и удалите ее (или, возможно, просто скройте ее). Если дальнейшая проверка на сервере обнаруживает проблему, она может вернуть страницу, использующую JavaScript, чтобы указать исходному окну повторно отобразить форму.
  • Используйте cookie сеанса и уникальный идентификатор формы (текущее время из new Date().getTime()); когда форма отправлена, отключите кнопку отправки, но сохраните ее, пока ответ не вернется. Сделать ответ установленным cookie сеанса с этим идентификатором, указывающим успех/сбой. Получайте окно, содержащее опрос формы для файла cookie каждую секунду или около того, и действуйте на результат, когда он его видит. (Я никогда не делал этого последнего, не сразу понял, почему это не сработает.)

Я ожидаю, что существует около дюжины других способов обмануть этого кота, но это три, которые приходят на ум.

(Edit) Если вы не отправляете другую цель, вы можете пойти дальше и сделать это - на скрытую iframe на той же странице. Это (возможно, в сочетании с вышеупомянутыми или другими ответами) может помочь вам получить пользовательский опыт, который вы ищете.

Ответ 2

Есть целый ряд действительно хороших причин, по которым IE это делает, и я уверен, что это не то, с чем кто-либо будет спорить, поэтому главная цель - как-то обойти его, чтобы сделать что-то лучше для ваших пользователей.

Иногда его стоит переосмыслить, как все делается. Возможно, отключите кнопку, используйте javascript, чтобы проверить, когда заполнены все поля, и отмените запрос ajax, когда они есть. Если ajax был успешным, включите кнопку. Это лишь одно предложение, я уверен, что будет больше...

Изменить: подробнее...

Простая подача (не AJAX), и если сбой проверки, отправьте страницу назад, а не вложение. Отправленная страница может содержать всю первоначально отправленную информацию (плюс любое сообщение об ошибке для пользователя), поэтому пользователю не нужно заполнять всю форму снова. И я также уверен, что будет больше идей...

Изменить: подробнее...

Я уверен, что вы видели этот тип вещей раньше - и да, это дополнительный клик (не идеальный, но не жесткий).... "если загрузка не удалась, нажмите здесь" → в в этом случае сделайте это так, как вы хотите это сделать, но добавьте новую ссылку/кнопку на страницу, когда возвращается AJAX, поэтому, если загрузка не удалась, они могут отправить уже проверенную форму из "прямого действия пользователя". И я уверен, что буду думать больше (или кто-то другой будет).....

Ответ 3

Я некоторое время борюсь с подобной проблемой. В моем случае отправка в скрытый iframe не работала, если мое веб-приложение было встроено в iframe на другом сайте (проблемы сторонних файлов cookie), если наш сайт не был добавлен в список доверенных сайтов.

Я обнаружил, что могу разбить загрузку в последовательности POST и GET. Сообщение возвращает короткий GUID, который может использоваться в запросе GET для инициирования загрузки. POST может выполнить проверку формы, а также вернуть идентификатор GUID в успешном ответе. После того, как клиент имеет идентификатор GUID, вы можете установить свойство src для скрытого элемента iframe для URL-адреса загрузки. Браузер видит заголовок 'Content-Disposition': 'attachement' и дает пользователю загрузочную ленту для загрузки файла.

Пока он работает во всех последних браузерах. К сожалению, для загрузки файла вам необходимо изменить API-интерфейс на стороне сервера.