TL/DR:如何可靠地通过FormPanel
加载XML响应?
我们在GWT中有一个Web应用程序,在大多数UI中使用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 包装器中)。我尝试了以下方法:
- 我最初使用了
Content-Type: text/html
(本地PHP测试脚本中的监督,生产代码中的错误)。在Firefox和Chrome中工作,但在IE(9)中不起作用,在IE(9)中,XML在IFrame中作为XML加载。 -
Content-Type: application/xml
哪个是有效载荷的正确选择。现在它在任何地方都不起作用,因为我们现在得到了最初只有IE在Chrome和FF中表现出的行为。 -
Content-Type: application/octet-stream
:不是一个好主意,它只是下载文件。 -
Content-Type: text/plain
:我希望这总是会触发 HTML/body 包装,它确实如此,但它也将所有内容包装在一个pre
元素中,所以它现在到处都失败了,但至少是可靠的。伟大。
经过一番挖掘,我发现显然GXT FormPanel
使用与GWT相同的FormPanelImpl
,因此两者的结果无论如何都是相同的。GWT的文件说(Sencha明智地隐瞒了):
后端服务器应该以
'text/html'
的内容类型进行响应,这意味着返回的文本将被视为HTML。如果服务器指定了任何其他内容类型,则在onFormSubmit
事件中发送的结果 html 在浏览器中将是不可预测的,并且FormHandler.onSubmitComplete(FormSubmitCompleteEvent)
事件可能根本不会触发。
但是,即使使用发送text/html
如果有效负载是 XML,则跨浏览器的行为也是不可预测的。
有没有通用的解决方案?还是我错过了一些非常琐碎的东西(我现在只看了三天的 GWT)?
编辑:我尝试在文件内容前面<html><body>
,因此即使IE也会在IFrame中有一个正文。嗯,它确实如此,但它也导致了一个非常非常奇怪的innerHTML
开始:
<?XML:NAMESPACE PREFIX = [default] ...
可以理解的是,XML 解析器会阻塞。
我的猜测是,一般来说,将 XML 包装在 HTML 上下文中而不执行任何特殊字符转义是不可靠的。我希望它至少会失败,像这样的XML文档
<a>
<b>
<html>
</html>
</b>
</a>
我们采取的方法是只发回一条小的"OK"消息,然后使用单独的请求从服务器获取(缓存的)内容。
或者,可能可以执行HTML编码/解码(或Base64,...
解决方法是覆盖类com.google.gwt.dom.client.Element.FormPanelImpl中的方法getContent。
代码更改是使用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错误。
乔迪。