首页 文章

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

提问于
浏览
4

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

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

我尝试使用"xhr.response"而不是成功方法参数中的"data",但它也不起作用 . 我在Chrome中的开发者工具中检查了响应 Headers ,并且设置正确 .
重要的是 - 在服务器端创建的所有excel工作簿都是正确的,因为它在以前的版本中工作时,数据是在URL中发送的,而不是在ajax帖子中发送的 .

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下载文件并打开下载窗口:

$.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);
        }

2 回答

  • 0

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

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

相关问题