ExtJS 5 - 从 POST servlet 请求下载文件

ExtJS 5 - Download file from POST servlet request

我尝试使用表单提交方法在 ExtJS 5 中实现导出功能。我看过以下 Whosebug link,它有帮助但不完全。

Extjs 4 (with a code for 3.4 below) downloading a file returned from a post request

在我的例子中,我在请求响应成功后遇到了一个问题,JSON 编码变得无效 error.Even 我试图将 reader 从 JSON reader 到其他字符串 reader(在 link 中提到),但由于某种原因它非常成功。

http://www.sencha.com/forum/showthread.php?86704-handling-xml-response-on-form-submit

代码:-

  var form = Ext.create('Ext.form.Panel',{
    timeout: 60000
  });
  var basicForm = form.getForm();
  basicForm.errorReader= new String();
    basicForm.submit({
        url     :  GRID_EXPORT_URL,
        method  : 'POST',
        headers : {
            "USER": user,
            "SERVERSESSIONID": serverSessionId,
            "Content-Type":"application/x-www-form-urlencoded"
        },  
        params  : {
            gridId:"dummyGrid",
            colDescs:"col1,Name"
        },              
        scope   : this,
        success : function(responseText){              
        },
        target: '_blank' 
    });  

错误信息:-

   [E] Ext.JSON.decode(): You're trying to decode an invalid JSON String: Code

来自 Java servlet(CSV) 的输出响应:-

    Id,Name
    13092,Thiru
    12767,Arasu
    117,Vinod

我认为由于这个编码问题,即使在请求之后 returns 200 成功状态;浏览器下载 window 没有弹出!非常感谢您的帮助,在此先感谢!

我已经修改了如下代码,但浏览器下载事件仍然没有发生,尽管响应是 200。

修改后的代码 Iframe/Form:-

onClickExport : function(){
    var body = Ext.getBody();
    var downloadFrame = body.createChild({
         tag: 'iframe',
         cls: 'x-hidden',
         id: 'app-upload-frame',
         name: 'uploadframe'
     });      
    var downloadForm = body.createChild({
         tag: 'form',
         cls: 'x-hidden',
         id: 'app-upload-form',
         target: 'app-upload-frame'
     });        
    Ext.Ajax.request ({
      url     : EXPORT_URL,
      method  : 'POST',
      form    : downloadForm,       
      timeout : 30 * 60 * 1000, // 30 Minutes should be OK.
      scope   : this,
      headers : {
            "USER": user,
            "SERVERSESSIONID": serverSessionId,
            "Content-Type":"application/x-www-form-urlencoded"
      },  
      params  : {
            gridId:"dummyGrid",
            colDescs:"col1,Name"
      }, 
      success : function (r) {
        alert("Success");
      },
      failure: function(r) {
        alert('error');
      }
    }); 

注意:我正在使用 Google Chrome 浏览器!

谢谢!

您有任何headers响应配置吗?

header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
// Disable caching
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1
header("Pragma: no-cache"); // HTTP 1.0
header("Expires: 0"); // Proxies

导出可以通过 ajax 调用实现,从响应中创建一个 Blob 并使用 msSaveBlob 保存。这适用于现代浏览器 ie10 及更高版本

onClickExport: function() {
    CUIF.Ajax.request({
        url: '......',
        method: 'POST',
        scope: this,
        params: {
           ...
           ...
         },
        success: function(data,response) {
            this.onExportSuccess(response);
        }
    });
},

onExportSuccess: function(response){
     this.getView().unmask("Loading...");
     var disposition = response.getResponseHeader('Content-Disposition');
     var filename = disposition.slice(disposition.indexOf("=")+1,disposition.length);
     var type = response.getResponseHeader('Content-Type');
     var blob = new Blob([response.responseText], { type: type });
     if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created These URLs will no longer resolve as the data backing the URL has been freed."
        window.navigator.msSaveBlob(blob, filename);
     } 
     else {
        var URL = window.URL || window.webkitURL;
        var downloadUrl = URL.createObjectURL(blob);
        if (filename) {
            // use HTML5 a[download] attribute to specify filename
            var a = document.createElement("a");
            // safari doesn't support this yet
            a.href = downloadUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
        } 
        setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
    }    
}

使用不可见表单和 0 高度 iframe 创建一个像这样的 Sencha OnPostDownloader 组件。

Ext.define('MyApp.view.OnPostDownload', {
  extend: 'Ext.Component',
  alias: 'widget.OnPostDownloader',
  autoEl: {
    tag: 'iframe',
    cls: 'x-hidden',
    src: Ext.SSL_SECURE_URL
  },
  postAndDownload: function (config) {
    var invsibleForm = Ext.create('Ext.form.Panel', {
      title: 'invsibleForm',
      standardSubmit: true,
      url: config.url,
      timeout: 120000,
      height: 0,
      width: 0,
      hidden: true,
      items: [ {
        xtype: 'hiddenfield',
        name: 'mydata',
        value: config.params
      } ]
    });

    invsibleForm.getForm().submit();
  }
});