似乎没有万无一失的解决方案,但我会尝试以下几种方法:
1) Use an iframe
而不是真正的 XHR 将数据 POST 到服务器,例如<form action="/something" target="myiframe">
where myiframe
is the name
隐藏的 iframe 的。这样,您的表单将使用 iframe(而不是您的主窗口)将数据提交到配置的 URL。您的服务器应将响应标头设置为application/octet-stream
(或二进制数据的某种 MIME 类型),以便浏览器触发下载。否则(如果在您的情况下返回 html),您可以只检索 iframe 的 body insideHTML 并将其显示在 UI 中的用户。虽然使用 iframe(或新窗口)而不是 XHR 听起来不是最好的主意,但此解决方案似乎是迄今为止最可靠的(并且具有最佳的浏览器支持)。
这是一个稍微修改过的例子扩展形式基本 http://docs.sencha.com/ext-js/4-0/#!/api/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
表单的参数submit行动。此功能没有记录,但您可以看到它被用于扩展表单操作提交 http://docs.sencha.com/ext-js/4-0/source/Submit.html#Ext-form-action-Submit源代码(您传递给的所有选项Ext.form.Basic.submit() http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.Basic-method-submit方法最终作为 Ext.form.action.* 实例的参数。
在我输入的示例代码中target: '_blank'
证明它可以立即工作(将创建一个新的浏览器窗口)。您可以稍后将其替换为 iframe 的名称,但我建议您首先测试表单如何将数据提交到常规新窗口,然后开发创建和处理 iframe 的逻辑。你必须自己在 iframe 内处理结果,我想。没那么难,看看Ext.data.Connection.upload() http://docs.sencha.com/ext-js/4-0/source/Connection.html#Ext-data-Connection-method-upload实现作为 iframe 处理的示例。
ExtJS 实际上已经使用了iframe
文件技术uploads. See 外部数据连接 http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Connection and Ext.form.field.Field.isFileUpload() http://docs.sencha.com/ext-js/4-0/#!/api/Ext.form.field.Field-method-isFileUpload了解它如何运作。
2)这里推荐:使用 HTML5/Javascript 生成并保存文件 https://stackoverflow.com/questions/2897619/using-html5-javascript-to-generate-and-save-a-file.
如果你不想走 iframe 方式,你可以尝试生成data URI从响应数据中导航到触发下载的 URI:
content = "Hello world!";
uriContent = "data:application/octet-stream," + encodeURIComponent(content);
window.location.href = uriContent;
再次强调,mimetype 在这里至关重要。这对我有用,但是您应该注意,浏览器对数据 URI 施加了大小限制(256Kb 是安全的选择)。
3)上述线程中的另一个答案链接到文件保存器.js https://github.com/eligrey/FileSaver.js库实现了(废弃?)w3 规范。使用与演示here http://eligrey.com/blog/post/saving-generated-files-on-the-client-side。它使用 [BlobBuilder] 生成二进制数据 blob,该数据进一步用于使用多种方法之一初始化下载。虽然此解决方案似乎有效,但它使用已弃用的 API,并且可能无法面向未来。