似乎没有防弹解决方案,但我会尝试几种方法:
1)使用iframe
而不是真正的 XHR 将数据发布到服务器,例如隐藏 iframe的<form action="/something" target="myiframe">
位置在哪里。这样,您的表单将使用 iframe(而不是您的主窗口)将数据提交到配置的 URL。您的服务器应将响应标头设置为(或二进制数据的其他 MIME 类型),以便浏览器触发下载。否则(如果在您的情况下返回 html),您只需检索 iframe 的正文 innerHTML 并在 UI 中将其显示给用户。虽然使用 iframe(或新窗口)而不是 XHR 听起来不是最好的主意,但这个解决方案似乎是迄今为止最可靠的(并且具有最好的浏览器支持)。myiframe
name
application/octet-stream
这是来自Ext.form.Basic文档页面的稍微修改的示例:
Ext.create('Ext.form.Panel', {
title: 'Basic Form',
renderTo: Ext.getBody(),
width: 350,
// Any configuration items here will be automatically passed along to
// the Ext.form.Basic instance when it gets created.
// *THIS* makes the form use a standard submit mechanism, not XHR
/**/standardSubmit: true,
// URL to submit to
url: 'save-form.php',
items: [{
fieldLabel: 'Field',
xtype: 'textfield',
name: 'theField'
}],
buttons: [{
text: 'Submit',
handler: function() {
// The getForm() method returns the Ext.form.Basic instance:
var form = this.up('form').getForm();
if (form.isValid()) {
// Submit the Ajax request and handle the response
form.submit({
success: function(form, action) {
Ext.Msg.alert('Success', action.result.msg);
},
failure: function(form, action) {
Ext.Msg.alert('Failed', action.result.msg);
},
// You can put the name of your iframe here instead of _blank
// this parameter makes its way to Ext.form.Basic.doAction()
// and further leads to creation of StandardSubmit action instance
/**/ target: '_blank'
});
}
}
}]
});
这里有两个关键参数(标有 的行/**/
):
standardSubmit: true
您传递给表单的配置将使其执行标准提交而不是 XHR。
- 将参数传递
target
给表单的提交操作。此功能未记录,但您可以在Ext.form.action.Submit源代码中看到它正在使用(您传递给Ext.form.Basic.submit()方法的所有选项最终都作为 Ext.form.action 的参数。 * 实例。
在示例代码中,我target: '_blank'
展示了它可以立即工作(将创建一个新的浏览器窗口)。您可以稍后将其替换为 iframe 的名称,但我建议您首先测试表单如何将数据提交到常规新窗口,然后开发创建和处理 iframe 的逻辑。想着,您将不得不自己在 iframe 中处理结果。没那么难,看Ext.data.Connection.upload()实现作为 iframe 处理的例子。
ExtJS 实际上已经使用了iframe
文件上传技术。请参阅Ext.data.Connection和Ext.form.field.Field.isFileUpload()了解它是如何工作的。
2)此处建议:使用 HTML5/Javascript 生成和保存文件。
如果您不想采用 iframe 方式,可以尝试从响应数据生成数据 URI并导航到该 URI 触发下载:
content = "Hello world!";
uriContent = "data:application/octet-stream," + encodeURIComponent(content);
window.location.href = uriContent;
同样,mimetype 在这里是必不可少的。这对我有用,但是您应该注意,浏览器对数据 URI 施加了大小限制(256Kb 是一个安全的选择)。
3)提到的线程中的另一个答案链接到FileSaver.js库,该库实现了(被放弃的?)w3 规范。用法和演示在这里。它使用 [BlobBuilder] 生成二进制数据块,进一步用于使用多种方法之一初始化下载。尽管此解决方案似乎可行,但它使用了已弃用的 API,并且可能不会面向未来。