GWT и Sencha GXT: результат FormPanel не выполняется

TL/DR: как загрузить ответ XML через FormPanel надежно?


У нас есть веб-приложение в GWT, использующее Sencha GXT для большей части пользовательского интерфейса. Мы используем GXT FormPanel загрузить файл в сценарий на стороне сервера (который просто отображает содержимое файла), чтобы получить содержимое локального файла в JS. В конце концов это можно сделать с помощью FileReader, но, очевидно, не в браузерах, которые этого не поддерживают.

FormPanel отправляет свою форму и загружает результат в скрытый IFrame, из которого содержимое извлекается с помощью следующего фрагмента (из FormPanelImpl.class):

try {
  // Make sure the iframe's window & document are loaded.
  if (!iframe.contentWindow || !iframe.contentWindow.document)
    return null;

  // Get the body's entire inner HTML.
  return iframe.contentWindow.document.body.innerHTML;
} catch (e) {
  return null;
}

Мы загружаем файл XML таким образом, и проблемная строка

return iframe.contentWindow.document.body.innerHTML;

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

  1. я использовал Content-Type: text/html изначально (недосмотр в локальном тестовом скрипте PHP, ошибка с моей стороны в рабочем коде). Работал в Firefox и Chrome, но не в IE (9), где XML был загружен как XML в IFrame.
  2. Content-Type: application/xml который был бы правильным для полезной нагрузки. Теперь это нигде не работает, потому что теперь мы получаем поведение, которое изначально было только в IE и в Chrome и FF.
  3. Content-Type: application/octet-stream: Не очень хорошая идея, он просто загружает файл.
  4. Content-Type: text/plain: Я надеялся, что это всегда вызовет перенос HTML/ тела, и это так, но это также оборачивает все в pre Элемент, так что теперь он терпит неудачу везде, но это по крайней мере надежно. Отлично.

После небольшой копки я узнал, что, по-видимому, GXT FormPanel использует то же самое FormPanelImpl от GWT, так что результаты одинаковы для обоих в любом случае. И документация GWT гласит (что Сенча мудро воздержался):

Предполагается, что внутренний сервер ответит типом содержимого 'text/html'Это означает, что возвращаемый текст будет рассматриваться как HTML. Если какой-либо другой тип контента указан сервером, то результат HTML отправляется в onFormSubmit событие будет непредсказуемым во всех браузерах, а FormHandler.onSubmitComplete(FormSubmitCompleteEvent) событие может не сработать вообще.

Впрочем, даже с отправкой text/html Поведение непредсказуемо во всех браузерах, если полезной нагрузкой является XML.

Есть ли общее решение для этого? Или я упускаю что-то ужасно тривиальное (я смотрю на GWT всего три дня)?

РЕДАКТИРОВАТЬ: я пытался предварения <html><body> к содержимому файла, так что даже IE будет иметь тело в IFrame. Ну, это так, но это также привело к очень, очень странному innerHTML начиная с:

<?XML:NAMESPACE PREFIX = [default] ...

который, разумеется, захлёбывает парсер XML.

2 ответа

Решение

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

<a>
  <b>
    <html>
    </html>
  </b>
</a>

Подход, который мы выбрали, заключается в том, чтобы просто отправить небольшое сообщение "ОК", а затем использовать отдельный запрос для получения (кэшированного) содержимого с сервера.

В качестве альтернативы, возможно, будет возможно выполнить кодирование / декодирование HTML (или Base64, ...)

Обходной путь - переопределить метод getContents в классе com.google.gwt.dom.client.Element.FormPanelImpl.

Изменение кода заключается в использовании textContent вместо innerHTML.

public native String getContents(Element iframe) /*-{
  try {
    // Make sure the iframe's window & document are loaded.
    if (!iframe.contentWindow || !iframe.contentWindow.document)
      return null;

    // Get the body's entire inner HTML.
    return iframe.contentWindow.document.body.textContent;
  } catch (e) {
    return null;
  }
}-*/;

Я не знаю, является ли это ошибкой GWT или нет.

Jordi.

Другие вопросы по тегам