Jquery ASP.NET MVC和FileAPI-无法打开下载的Excel文件

Jquery ASP.NET MVC和FileAPI-无法打开下载的Excel文件,jquery,excel,model-view-controller,Jquery,Excel,Model View Controller,我向上看这里- 在这里- 并提出了使用以下代码段从我的服务器下载现有文件的解决方案: JavaScript调用- function GetExcelData() { debugger; var data = { prop: 1, myArray: [1, "two", 3] }; var params = JSON.stringify(data); var url = '/Export/DownloadWidgetDataFile'; $.ajax({

我向上看这里- 在这里-

并提出了使用以下代码段从我的服务器下载现有文件的解决方案:

JavaScript调用-

function GetExcelData()
{
    debugger;
    var data = { prop: 1, myArray: [1, "two", 3] };
    var params = JSON.stringify(data);
    var url = '/Export/DownloadWidgetDataFile';
    $.ajax({
        type: "POST",
        url: url,
        data: "pInputData="+params,
        success: function (response, status, xhr) {
            // check for a filename
            var filename = "";
            var disposition = xhr.getResponseHeader('Content-Disposition');
            if (disposition && disposition.indexOf('attachment') !== -1) {
                var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                var matches = filenameRegex.exec(disposition);
                if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
            }

            var type = xhr.getResponseHeader('Content-Type');
            var blob = new Blob([response], { 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
                    if (typeof a.download === 'undefined') {
                        window.location = downloadUrl;
                    } else {
                        a.href = downloadUrl;
                        a.download = filename;
                        document.body.appendChild(a);
                        a.click();
                    }
                } else {
                    window.location = downloadUrl;
                }

                setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
            }
            alert('Success Called');
        },
        error: function (jqXHR, text, status) {
            alert('error');
        }

    });
}
以及控制器中的动作方法:

[HttpPost]
        public FileResult DownloadWidgetDataFile(string pInputData)
        {
            string tFileDownloadPath = Server.MapPath("../Export/DownloadFile.xlsx");
            System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=DownloadFile.xlsx");
            System.Web.HttpContext.Current.Response.End();
            return File(tFileDownloadPath, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");          

        }
现在一切似乎都很好,但当我尝试打开下载的ExcelFile时,会出现一个错误,显示: “Excel无法打开文件…因为文件格式或文件扩展名无效。请验证文件是否已损坏…”


无法找出导致问题的原因。

有两个问题。首先,jQuery ajax调用似乎会破坏二进制数据,因此应改用XMLHttpRequest:

var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
    if (this.status === 200) {
        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }
        var type = xhr.getResponseHeader('Content-Type');

        var blob = new Blob([this.response], { 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
                if (typeof a.download === 'undefined') {
                    window.location = downloadUrl;
                } else {
                    a.href = downloadUrl;
                    a.download = filename;
                    document.body.appendChild(a);
                    a.click();
                }
            } else {
                window.location = downloadUrl;
            }

            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
        }
    }
};
xhr.send("pInputData=" + params);
其次,MVC代码在发送文件数据之前关闭响应。以下是添加标头然后发送文件数据的正确方法:

[HttpPost]
public FileResult DownloadWidgetDataFile(string pInputData)
{
    string tFileDownloadPath = Server.MapPath("../Export/DownloadFile.xlsx");
    Response.AddHeader("Content-Disposition", "attachment;filename=DownloadFile.xlsx");
    return File(tFileDownloadPath, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}

完美的非常感谢。在我的例子中,任何关于使其在IE9中工作的指针(或没有blob支持?)在响应中添加额外的标题都会导致无效响应:
ERR\u Response\u HEADERS\u MULTIPLE\u CONTENT\u DISPOSITION
这涵盖了我的所有浏览器要求(IE/Safar/Firefox/Chrome)-我唯一需要删除的是内容配置,否则会很完美。