Extjs 4通过ajax调用下载文件

时间:2022-04-08 10:07:49

The problem is very simple: i have to download a file when i submit a form, it's an ajax call when the form is submitted which lets me build a file with the data taken from the form, server side, and then send it as a link to an alert. The fact is that my boss want the file to be downloaded directly and not through a link in an alert. So i had to make sure that the file is available server side through tornado(web):

问题很简单:当我提交表单时我必须下载一个文件,当提交表单时它是一个ajax调用,它允许我使用从表单,服务器端获取的数据构建一个文件,然后将其作为一个链接到提醒。事实是我的老板希望直接下载文件,而不是通过警报中的链接。所以我必须通过龙卷风(web)确保文件在服务器端可用:

        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition', 'attachment; filename=clients_counter.zip')
        with open("static/clients_counter.zip", 'r') as f:
            while True:
                data = f.read()
                if not data:
                    break
        self.write(data)
        self.finish()

The server side code seems to work fine, but the client side (extjs4.1) is really a nightmare. This is how my ajax call looks like now, and it doesn't work:

服务器端代码似乎工作正常,但客户端(extjs4.1)真的是一场噩梦。这就是我的ajax调用现在的样子,它不起作用:

Ext.Ajax.request({
method : "GET",
url : 'http://whatever.com/count?client='+client+'&start='+start+'&end='+end,
timeout : 30000,
success :
         function (response) {
    //Ext.Msg.alert(response.responseText);
            desktop.getWindow('count-win').doClose();
            return response;
       }//handler,
     failure : 
     function(response) {
    alert("Wrong request");
    }});

7 个解决方案

#1


9  

After reading on various sources from Ext JS forum and here in *, below is the approach I've chosen (using Ext JS version 4.2.1):

在阅读了Ext JS论坛的各种来源和*之后,下面是我选择的方法(使用Ext JS 4.2.1版):

downloadFile: function(config){
    config = config || {};
    var url = config.url,
        method = config.method || 'POST',// Either GET or POST. Default is POST.
        params = config.params || {};

    // Create form panel. It contains a basic form that we need for the file download.
    var form = Ext.create('Ext.form.Panel', {
        standardSubmit: true,
        url: url,
        method: method
    });

    // Call the submit to begin the file download.
    form.submit({
        target: '_blank', // Avoids leaving the page. 
        params: params
    });

    // Clean-up the form after 100 milliseconds.
    // Once the submit is called, the browser does not care anymore with the form object.
    Ext.defer(function(){
        form.close();
    }, 100);

}

#2


5  

I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:

我有一个类似的问题试图在Ajax调用中下载Excel文件我这样解决了它:

Make a standard sumbit instead of Ajax.

制作标准的sumbit而不是Ajax。

var form = Ext.create('Ext.form.Panel', { // this wolud be your form 
    standardSubmit: true,         // this is the important part 
    url: '../ObtenerArchivoAdjuntoServlet' 
});

form.submit({
    params: {
       nombreArchivo: nombreArchivo
    }
});

After this you would be able return the desired file.

在此之后,您将能够返回所需的文件。

#3


2  

I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:

我认为你可以采取更容易的解决方案。忘记ajax,只需让普通的旧js为你打开文件:

window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)

This will open a new tab and start the download from there.

这将打开一个新选项卡并从那里开始下载。

#4


1  

After extracting/reading many posts, I managed to get this simple method to work..

提取/阅读很多帖子后,我设法让这个简单的方法工作..

                Ext.create('Ext.form.Panel', {
                    renderTo: Ext.getBody(),
                    standardSubmit: true,
                    url: 'URL'
                }).submit({params: {'PARAM1': param1, 'PARAM2': param2}});

#5


0  

I just had to ad to the success function of the ajax request:

我只需要广告ajax请求的成功功能:

window.open('urltothefile.ext')

#6


0  

The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.

以下代码用于使用extjs 5或6下载文件。将以下代码添加到方法并调用此按钮以执行按钮操作。这将直接下载文件而不是在新选项卡中打开。

use an iframe like this:

像这样使用iframe:

/**
 * prints the file
 */
printReport: function () {
    var url = 'downloadURL';
    Ext.Ajax.request({
        url: url,
        method: 'GET',
        autoAbort: false,
        success: function(result) {
            if(result.status == 204) {
                Ext.Msg.alert('Empty Report', 'There is no data');
            } else if(result.status == 200) {
                Ext.DomHelper.append(Ext.getBody(), {
                    tag:          'iframe',
                    frameBorder:  0,
                    width:        0,
                    height:       0,
                    css:          'display:none;visibility:hidden;height:0px;',
                    src:          url
                });
            }
        },
        failure: function() {
            //failure here will automatically
            //log the user out as it should
        }
    });
}

Copied the answer from extjs forum

复制了extjs论坛的答案

Option:2 If you want to open the file in new tab

选项:2如果要在新选项卡中打开文件

    /**
 * open file in tab
 */
openReport: function () {
    var url = 'downloadURL';
    Ext.Ajax.request({
        url: url,
        method: 'GET',
        autoAbort: false,
        success: function(result) {
            if(result.status == 204) {
                Ext.Msg.alert('Empty Report', 'There is no data');
            } else if(result.status == 200) {
                var win = window.open('', '_blank');
                win.location = url;
                win.focus();
            }
        },
        failure: function() {
            //failure here will automatically
            //log the user out as it should
        }
    });
}

#7


0  

You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.

你不能使用ajax下载文件。我在extjs中实现了文件下载,就像ajax一样。看博客ajaxlikefiledownload。

FileDownload.downloadFile = function(arguments) {

var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];

var body = Ext.getBody();

var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});

var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});


if (params)
{
    for (var paramName in params)
    {

        form.createChild({
            tag:'input',
            cls:'x-hidden',
            id:'hiddenform-'+paramName,
            type: 'text',
            text: params[paramName],
            target:'iframe',
            value: params[paramName],
            name: paramName
            });

    }
}

form.dom.submit();

FileDownload.isFinished(successCallback,failureCallback);

};

FileDownload.isFinished = function(successCallback,failureCallback) {

//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
    //Remove cookie call success callback 
    Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
    Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
    successCallback();
    return;
} 

//Check for error / IF any error happens then frame will load with content
try {
    if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
        Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
        Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
        failureCallback();
        //Cleanup
        Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = ""; 

        return;
    }
} 
catch (e) {
    console.log(e);
}

console.log('polling..');
// If we are here, it is not loaded. Set things up so we check   the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);

};

Usage :

FileDownload.downloadFile({
  url : url,
  params : params,
  success : function(){
   //Success call back here
  },
  failure : function(){
   //Failure callbak here
  }
});

In the http response you need to add a cookie nammed fileDownload = true

在http响应中,您需要添加一个cookie nammed fileDownload = true

#1


9  

After reading on various sources from Ext JS forum and here in *, below is the approach I've chosen (using Ext JS version 4.2.1):

在阅读了Ext JS论坛的各种来源和*之后,下面是我选择的方法(使用Ext JS 4.2.1版):

downloadFile: function(config){
    config = config || {};
    var url = config.url,
        method = config.method || 'POST',// Either GET or POST. Default is POST.
        params = config.params || {};

    // Create form panel. It contains a basic form that we need for the file download.
    var form = Ext.create('Ext.form.Panel', {
        standardSubmit: true,
        url: url,
        method: method
    });

    // Call the submit to begin the file download.
    form.submit({
        target: '_blank', // Avoids leaving the page. 
        params: params
    });

    // Clean-up the form after 100 milliseconds.
    // Once the submit is called, the browser does not care anymore with the form object.
    Ext.defer(function(){
        form.close();
    }, 100);

}

#2


5  

I had a similar problem trying to download an Excel File in an Ajax call I solved it this way:

我有一个类似的问题试图在Ajax调用中下载Excel文件我这样解决了它:

Make a standard sumbit instead of Ajax.

制作标准的sumbit而不是Ajax。

var form = Ext.create('Ext.form.Panel', { // this wolud be your form 
    standardSubmit: true,         // this is the important part 
    url: '../ObtenerArchivoAdjuntoServlet' 
});

form.submit({
    params: {
       nombreArchivo: nombreArchivo
    }
});

After this you would be able return the desired file.

在此之后,您将能够返回所需的文件。

#3


2  

I think you can take a much easier solution. Forget about the ajax, and just get plain old js to open the file for you:

我认为你可以采取更容易的解决方案。忘记ajax,只需让普通的旧js为你打开文件:

window.open('http://whatever.com/count?client='+client+'&start='+start+'&end='+end)

This will open a new tab and start the download from there.

这将打开一个新选项卡并从那里开始下载。

#4


1  

After extracting/reading many posts, I managed to get this simple method to work..

提取/阅读很多帖子后,我设法让这个简单的方法工作..

                Ext.create('Ext.form.Panel', {
                    renderTo: Ext.getBody(),
                    standardSubmit: true,
                    url: 'URL'
                }).submit({params: {'PARAM1': param1, 'PARAM2': param2}});

#5


0  

I just had to ad to the success function of the ajax request:

我只需要广告ajax请求的成功功能:

window.open('urltothefile.ext')

#6


0  

The following code used to download the file using extjs 5 or 6. Add the following code to method and invoke this for button action. This downloads the file directly insteadof opening in new tab.

以下代码用于使用extjs 5或6下载文件。将以下代码添加到方法并调用此按钮以执行按钮操作。这将直接下载文件而不是在新选项卡中打开。

use an iframe like this:

像这样使用iframe:

/**
 * prints the file
 */
printReport: function () {
    var url = 'downloadURL';
    Ext.Ajax.request({
        url: url,
        method: 'GET',
        autoAbort: false,
        success: function(result) {
            if(result.status == 204) {
                Ext.Msg.alert('Empty Report', 'There is no data');
            } else if(result.status == 200) {
                Ext.DomHelper.append(Ext.getBody(), {
                    tag:          'iframe',
                    frameBorder:  0,
                    width:        0,
                    height:       0,
                    css:          'display:none;visibility:hidden;height:0px;',
                    src:          url
                });
            }
        },
        failure: function() {
            //failure here will automatically
            //log the user out as it should
        }
    });
}

Copied the answer from extjs forum

复制了extjs论坛的答案

Option:2 If you want to open the file in new tab

选项:2如果要在新选项卡中打开文件

    /**
 * open file in tab
 */
openReport: function () {
    var url = 'downloadURL';
    Ext.Ajax.request({
        url: url,
        method: 'GET',
        autoAbort: false,
        success: function(result) {
            if(result.status == 204) {
                Ext.Msg.alert('Empty Report', 'There is no data');
            } else if(result.status == 200) {
                var win = window.open('', '_blank');
                win.location = url;
                win.focus();
            }
        },
        failure: function() {
            //failure here will automatically
            //log the user out as it should
        }
    });
}

#7


0  

You cannot use ajax to download file. I've implemented file downloading in extjs which is like ajax. see the blog ajaxlikefiledownload.

你不能使用ajax下载文件。我在extjs中实现了文件下载,就像ajax一样。看博客ajaxlikefiledownload。

FileDownload.downloadFile = function(arguments) {

var url = arguments['url'];
var params = arguments['params'];
var successCallback = arguments['success'];
var failureCallback = arguments['failure'];

var body = Ext.getBody();

var frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenframe-frame',
name:'iframe'
});

var form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: 'POST',
target:'iframe'
});


if (params)
{
    for (var paramName in params)
    {

        form.createChild({
            tag:'input',
            cls:'x-hidden',
            id:'hiddenform-'+paramName,
            type: 'text',
            text: params[paramName],
            target:'iframe',
            value: params[paramName],
            name: paramName
            });

    }
}

form.dom.submit();

FileDownload.isFinished(successCallback,failureCallback);

};

FileDownload.isFinished = function(successCallback,failureCallback) {

//Check if file is started downloading
if (Ext.util.Cookies.get('fileDownload') && Ext.util.Cookies.get('fileDownload')=='true' ) {
    //Remove cookie call success callback 
    Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
    Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
    successCallback();
    return;
} 

//Check for error / IF any error happens then frame will load with content
try {
    if(Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML.length>0){
        Ext.util.Cookies.set('fileDownload', null, new Date("January 1, 1970"),application.contextPath+'/');
        Ext.util.Cookies.clear('fileDownload',application.contextPath+'/');
        failureCallback();
        //Cleanup
        Ext.getDom('hiddenframe-frame').contentDocument.body.innerHTML = ""; 

        return;
    }
} 
catch (e) {
    console.log(e);
}

console.log('polling..');
// If we are here, it is not loaded. Set things up so we check   the status again in 100 milliseconds
window.setTimeout('FileDownload.isFinished('+successCallback+','+failureCallback+')', 100);

};

Usage :

FileDownload.downloadFile({
  url : url,
  params : params,
  success : function(){
   //Success call back here
  },
  failure : function(){
   //Failure callbak here
  }
});

In the http response you need to add a cookie nammed fileDownload = true

在http响应中,您需要添加一个cookie nammed fileDownload = true