Extjs 4(下面是3.4的代码)下载了一个post请求返回的文件



我看到过与此略有相关的问题,但没有一个能回答我的问题。我设置了一个Ext.Ajax.request,如下所示:

var paramsStringVar = 'param1=1&param2=two&param3=something&param4=etc';
Ext.Ajax.request({
  url: '/cgi-bin/url.pl',
  method:'POST',
  params:paramsStringVar,
  timeout:120000,
  success: function(response, opts){
    var objhtml = response.responseText; //content returned from server side
    console.log(objhtml);
  }
});

此请求从后端检索适当的内容。一个参数是outputType,它可以取值{html、excel、csv}。当返回html显示时,我能够正确地处理和显示它。现在来谈谈问题。。。

当我将outputType参数设置为csv或excel时,我会根据要求返回csv或tsv(excel)的适当内容。但是,我不想要内容,我想要一个下载文件的提示(csv或excel)。如何让浏览器自动提示用户下载文件,而不仅仅是在extjs中检索文本内容?

版本4.07,所以我不能使用任何仅4.1的功能

似乎没有防弹解决方案,但我会尝试几种方法:

1)使用iframe而不是真正的XHR将数据POST到服务器,例如<form action="/something" target="myiframe">,其中myiframe是隐藏iframe的name。这样,您的表单将使用iframe(而不是主窗口)向配置的URL提交数据。您的服务器应该将响应标头设置为application/octet-stream(或二进制数据的其他MIME类型),以便浏览器触发下载。否则(如果在您的案例中返回html),您只需检索iframe的主体innerHTML并在UI中向用户显示它。虽然使用iframe(或新窗口)而不是XHR听起来不是最好的主意,但该解决方案似乎是迄今为止最可靠的(并且具有最好的浏览器支持)。

以下是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'                        
                });
            }
        }
    }]
});

这里有两个关键参数(标有/**/的行):

  1. 传递给表单的standardSubmit: true配置将使其进行标准提交,而不是XHR
  2. target参数传递给表单的提交操作。这个功能没有文档记录,但你可以看到它在Ext.form.action.Submit源代码中被使用(你传递给Ext.form.Basic.Submit()方法的所有选项最终都是Ext.form.action.*实例的参数

在示例代码中,我放置了target: '_blank'来演示它可以立即工作(将创建一个新的浏览器窗口)。稍后您可以将其替换为iframe的名称,但我建议您首先测试表单如何将数据提交到常规的新窗口,然后开发创建和处理ifame的逻辑。你必须自己在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]生成二进制数据的blob,该blob进一步用于使用几种方法之一初始化下载。虽然这个解决方案似乎有效,但它使用了不推荐使用的API,可能不会经得起未来的考验。

下面是我的解决方案。这就是我目前的工作方式。响应会根据text.csv的响应类型生成下载/打开提示。请注意,不需要iFrame或对iFrame的引用。我花了很多时间在iFrame的需求上,这实际上破坏了我的解决方案。生成下载提示不需要iFrame。所需要的是一个类似于此的请求(提交),以及一个生成具有text/csv响应标头的适当csv的后端。

var hiddenForm = Ext.create('Ext.form.Panel', {
  title:'hiddenForm',
  standardSubmit: true,
  url: /cgi-bin/url.pl
  timeout: 120000,
  height:0,
  width: 0,
  hidden:true,
  items:[
    {xtype:'hiddenField', name:'field1', value:'field1Value'},
    // additional fields
  ]
})
hiddenForm.getForm().submit()

标准提交行是至关重要的

您不需要创建表单面板并将其隐藏在extjs文件中。我们可以添加一个html表单,点击extjs文件中的按钮,我们就可以使用url提交表单。这将在IE和chrome浏览器中都有效。以下是我尝试过的代码,它运行良好,

<form action="<%=fullURL%>/DownloadServlet.do" method="get" id="downloadForm"   name="downloadForm" target="_self">
</form>
click: 
  {
     fn: function()
    { 
       document.getElementById('downloadForm').submit();    
    }
  }   

让它在ExtJS 3.4:上工作

        var hiddenForm = new Ext.FormPanel({
            id:'hiddenForm',
            region: 'south',
            method: 'POST',
            url: "/cgi/test.wsgi",
            height: 0,
            standardSubmit: true,
            hidden:true,
            items:[
                {xtype:'hidden', name:'p', value:p},
                {xtype:'hidden', name:'g', value:g},
                // ...
            ],
        });
        linkThis = new Ext.Button({
            text: 'Download this CSV',
            handler: function() {
                hiddenForm.getForm().submit();
            },
            maxHeight: 30,
        });

请记住,为了使其工作,您应该将hiddenForm放在任何容器中(即,放在按钮的同一外部窗口中),例如:

  risultatiWindow = new Ext.Window({
            title: 'CSV Export',
            height: 400,
            width: 500,
            ....
            items: [...., hiddenForm]
 });

最新更新