【问题标题】:Get excel file (.xlsx) from server response in ajax从ajax中的服务器响应获取excel文件(.xlsx)
【发布时间】:2018-04-18 11:36:08
【问题描述】:

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

也许问题在于 Blob 构造函数中使用了不适当的数据类型?

我尝试使用“xhr.response”而不是成功方法参数中的“数据”,但它也不起作用。我在 Chrome 的开发人员工具中检查了响应标头,它们设置正确。
重要的是 - 在服务器端创建的所有 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);
    }

My Ajax 下载文件并打开下载窗口:

$.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]*=((['"]).*?\2|[^;\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);
        }

【问题讨论】:

    标签: javascript ajax excel content-type content-disposition


    【解决方案1】:

    看起来 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();
    

    【讨论】:

    • 天哪,非常感谢您的回答。你是最棒的!
    • fileName 第 16 行尚未定义。你在哪里定义的?
    • @Möoz 之前已经设置好了。但在这种情况下,这并不重要,因为它可能是“My_File.xlsx”之类的东西
    • 我可以下载文件,但是当我打开它时显示“抱歉,我们找不到 C:\mypath[object Object],[object Object],....[object Ob.xls. 是否有可能被移动、重命名或删除?”还有在下载过程中是否可以更改文件名?
    【解决方案2】:

    经过多次搜索从 Web 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);
                        }
                    });
    
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我尝试过使用responseType: 'arraybuffer',但它失败了,因为可能是text 不合适的responseType。但是我通过直接创建 XMLHttpRequest 解决了这个问题。下面评论中的工作代码。
      猜你喜欢
      • 2015-02-12
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      相关资源
      最近更新 更多