4

我已经看到与此略有相关的问题,但没有一个可以回答我的问题。我已经设置了一个 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 唯一的功能

4

4 回答 4

7

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

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

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

  1. standardSubmit: true您传递给表单的配置将使其执行标准提交而不是 XHR。
  2. 将参数传递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.ConnectionExt.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,并且可能不会面向未来。

于 2012-08-02T20:19:42.917 回答
6

下面是我的解决方案。这就是我目前的工作方式。响应根据文本/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()

标准提交行至关重要

于 2012-08-07T19:56:43.860 回答
0

您无需创建表单面板并将其隐藏在您的 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();    
    }
  }   
于 2013-11-13T05:22:22.277 回答
0

要让它在 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 放在任何容器中(即在按钮的同一个 Ext.Window 中),例如:

  risultatiWindow = new Ext.Window({
            title: 'CSV Export',
            height: 400,
            width: 500,
            ....
            items: [...., hiddenForm]
 });
于 2015-06-24T09:29:11.780 回答