There seems to be no bulletproof solution, but there are several approaches that I would try:
1) Use iframe instead of real XHR data for POST on the server, for example. <form action="/something" target="myiframe"> where myiframe is the name your hidden iframe. This way, your form will use an iframe (not your main window) to send data to the configured URL. The server should set the response header as application/octet-stream (or some kind of MIME for binary data), so the browser starts the download. Otherwise (if html is returned in your case) you can just get the iframe body innerHTML and display it to the user in the user interface. Although using an iframe (or new window) instead of XHR does not seem like a better idea, this solution seems to be the most reliable so far (and with better browser support).
Here is a slightly modified example from Ext.form.Basic docs:
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' }); } } }] });
There are two key parameters here (lines marked with /**/ ):
standardSubmit: true config, which you submit to your form will make it standard, not XHR.- Passing the
target parameter to the form submit action. This function is not documented, but you can see that it is used in the Ext.form.action.Submit source code (all the parameters that you pass to the Ext.form.Basic.submit () Method ultimately as parameters to the Ext.form instance .action. *.
In the sample code, I put target: '_blank' to demonstrate that it works immediately (it will create a new browser window). You can replace it with the name of your iframe later, but I suggest that you first check how your form passes data to a regular new window, and then develops the logic that creates and processes the iframe. I think you have to process the result inside the iframe. It's not that complicated, see the implementation of Ext.data.Connection.upload () for an example of iframe processing.
ExtJS actually already uses the iframe method for the uploads file. See Ext.data.Connection and Ext.form.field.Field.isFileUpload () for an understanding of how this might work.
2) Suggested here: Using HTML5 / Javascript to create and save a file .
If you do not want to follow the iframe path, you can try to create a URI of data from the response data and proceed to download using the URI:
content = "Hello world!"; uriContent = "data:application/octet-stream," + encodeURIComponent(content); window.location.href = uriContent;
Again, the mimetic is very important here. This worked for me, however you should note that browsers impose a size limit on the data URI (256 Kbps is a safe bet).
3) Another answer in the mentioned topic refers to the FileSaver.js library implements (abandoned?) W3 spec. Use and demo here . It uses [BlobBuilder] to generate blob binary data, which are then used to initialize the download using one of several methods. Although this solution seems to work, it uses legacy APIs and cannot be promising.