从 ajax 中的服务器响应获取 excel 文件 (.xlsx)

Get excel file (.xlsx) from server response in ajax

我在获取 excel 文件并在收到对该文件的响应(成功 ajax 方法)后在浏览器中打开下载 window 时遇到问题。我有合适的 Content-Type and Content-Disposition headers,我尝试在 js 中使用 Blob 但我无法实现我想要的 - 简单的文件下载。
我完成了 ajax 的几个版本,下面是其中一个。我开发了 ajax which returns excel 文件,但我无法正确打开它,因为它已损坏(尽管有 .xlsx 扩展名)。

问题可能出在 Blob 构造函数中使用了不合适的数据类型?

我尝试使用 "xhr.response" 而不是成功方法参数中的 "data",但它也不起作用。我在 Chrome 的 Developer Tools 中检查了 Response Headers,它们设置正确。
重要的是 - 在服务器端创建的所有 excel 工作簿都是正确的,因为当数据在 URL 中发送时它在以前的版本中有效,而不是在 ajax post 中。

下面Java/Spring服务器端的控制器方法:

response.reset();
response.setContentType("application/vnd.ms-excel");
response.addHeader("Content-Disposition","attachment;filename=\"" + className + " " +  title + ".xlsx\"");
    try (ServletOutputStream output = response.getOutputStream()){
        workbook.write(output);
        output.flush();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

我的Ajax下载文件并打开下载window:

$.ajax({
    url: myUrl,
    type: 'POST',
    data: myData,
    success: function(data, status, xhr) {
        var contentType = 'application/vnd.ms-excel';

        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }
        console.log("FILENAME: " + filename);

        try {
            var blob = new Blob([data], { type: contentType });

            var downloadUrl = URL.createObjectURL(blob);
            var a = document.createElement("a");
            a.href = downloadUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();

        } catch (exc) {
            console.log("Save Blob method failed with the following exception.");
            console.log(exc);
        }

我们最近遇到了完全相同的麻烦。对我们来说,当我们将 responseType: 'arraybuffer' 添加到 ajax 参数时,它开始起作用。最好使用 lib https://github.com/eligrey/FileSaver.js/ 而不是手动单击 link,因为此工具也会撤销内存。

看起来 JQuery 在处理来自响应的二进制数据时遇到了一些问题。我只使用了 XMLHttpRequest 并将所有数据添加到 URL.

var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';

request.onload = function(e) {
    if (this.status === 200) {
        var blob = this.response;
        if(window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, fileName);
        }
        else{
            var downloadLink = window.document.createElement('a');
            var contentTypeHeader = request.getResponseHeader("Content-Type");
            downloadLink.href = window.URL.createObjectURL(new Blob([blob], { type: contentTypeHeader }));
            downloadLink.download = fileName;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
           }
       }
   };
   request.send();

经过多次搜索,从网络 API 中获取了一个包含 Unicode 内容的 excel 文件。最后,这段代码对我有用:

$.ajax({
                type: 'GET',
                cache: false,
                url: "https://localhost:44320/WeatherForecast",
              
                xhrFields: {
                    // make sure the response knows we're expecting a binary type in return.
                    // this is important, without it the excel file is marked corrupted.
                    responseType: 'arraybuffer'
                }
            })
                .done(function (data, status, xmlHeaderRequest) {
                    var downloadLink = document.createElement('a');
                    var blob = new Blob([data],
                        {
                            type: xmlHeaderRequest.getResponseHeader('Content-Type')
                        });
                    var url = window.URL || window.webkitURL;
                    var downloadUrl = url.createObjectURL(blob);
                    var fileName = '';

                  

                    if (typeof window.navigator.msSaveBlob !== 'undefined') {
                        window.navigator.msSaveBlob(blob, fileName);
                    } else {
                        if (fileName) {
                            if (typeof downloadLink.download === 'undefined') {
                                window.location = downloadUrl;
                            } else {
                                downloadLink.href = downloadUrl;
                                downloadLink.download = fileName;
                                document.body.appendChild(downloadLink);
                                downloadLink.click();
                            }
                        } else {
                            window.location = downloadUrl;
                        }

                        setTimeout(function () {
                            url.revokeObjectURL(downloadUrl);
                        },
                            100);
                    }
                });