2012-06-29 3 views
3

TL/DR: Как надежно загрузить ответ XML через FormPanel?GWT и Sencha GXT: результат 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/body, но оно также обертывает все в элементе pre, поэтому теперь он выходит из строя повсюду, но, по крайней мере, надежно. Отлично.

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

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

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

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

EDIT: Я попытался добавить <html><body> к содержимому файла, поэтому даже IE будет иметь тело в IFrame.Ну, это так, но это также привело к очень, очень странный innerHTML начиная с:

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

которую XML-парсер по понятным причинам давится.

ответ

1

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

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

подход, который мы приняли, чтобы просто отправить обратно маленький «OK» сообщение, а затем использовать отдельный запрос, чтобы получить (кэшированные) содержимое из сервер.

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

+0

Любое кодирование по-прежнему создает некоторую боль в настоящее время по двум причинам: (a) Это GWT, поэтому в значительной степени просто Java-язык без Java-стандартной библиотеки, что означает, что большинство способов декодирования Base64 не будут выполняться. И (b) Кодирование выполняется на уровне байтов, что требует от меня выяснить кодировку (надеюсь, UTF-8, но вы никогда не узнаете) впоследствии. Поскольку GWT не имеет никаких положений, связанных с этим, я все еще в недоумении, как с этим справиться. По крайней мере, я бы сказал, что это проблема документации GWT (как если бы этого было недостаточно). – Joey

+0

@Joey: Я согласен, документация (GWT) FormPanel может отсутствовать в нескольких деталях (GXT еще один). Мы нашли множество преимуществ в использовании отдельного запроса: он позволяет упростить повторную загрузку, параллельную загрузку с помощью диспетчера загрузки, улучшенная безопасность (с сервлетом, который отображает все, что вы отправляете, может быть опасным), ... –

+0

Я решил это сейчас используя этот метод в [этом ответе] (http://stackoverflow.com/a/6491785/73070). По сути, это замена специальных символов объектами HTML и декодирование на стороне клиента. Единственная проблема, с которой я столкнулся сейчас, - случайные исключения в Chrome, но * только * в режиме размещения, но это еще один вопрос: ;-). Загрузка загруженного файла по отдельности была бы слишком переработана здесь прямо сейчас, и я даже не знаю, есть ли у нас способы записи файлов, где он размещен из эхо-скрипта, поэтому я решил это сейчас. – Joey

0

Чтобы обойти проблему, переопределить метод 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.

+0

И как я могу заставить FormBanel использовать мою производную реализацию? – Joey

+0

Я открыл билет http://code.google.com/p/google-web-toolkit/issues/detail?id=7535, но, видимо, они не исправят его, потому что документ для FormPanel говорит, что он может только возвращать текст/HTML. –

+0

новые FormPanelImpl() { \t \t \t \t \t общественных нативные струнных getContents (com.google.gwt.dom.client.Element IFrame)/* - {JSCode} - * /; \t \t \t \t \t}; –

Смежные вопросы