【发布时间】:2012-07-19 22:34:50
【问题描述】:
TL/DR:如何可靠地通过FormPanel 加载 XML 响应?
我们在 GWT 中有一个 Web 应用程序,它使用 Sencha GXT 来处理大部分 UI。我们使用 GXT FormPanel 将文件上传到服务器端脚本(它只是回显文件的内容)以在 JS 中获取本地文件的内容。最终这可以通过 FileReader 完成,但显然不能在不支持它的浏览器中完成。
FormPanel 提交其表单并将结果加载到隐藏的 IFrame 中,使用以下 sn-p(来自 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 解析器可以理解的阻塞。
【问题讨论】: