XLSX 客户端从后端 api 响应中保存:二进制字符串、应用程序/八位字节流

Posted

技术标签:

【中文标题】XLSX 客户端从后端 api 响应中保存:二进制字符串、应用程序/八位字节流【英文标题】:XLSX client save from backend api response: binary string, application/octet-stream 【发布时间】:2018-12-19 21:00:43 【问题描述】:

我需要将 XLSX 文件保存在我从 XHR 获取到 api 的前端。

在 api 响应中我得到了这个标题:

    Content-Type: application/octet-stream
    content-disposition: attachment; filename = OrdersList-253CREATED0.xlsx

以及响应正文的一部分:

PKõzMdocProps/core.xml­MKÄ0ïý!÷vVd-mQÅ++ÞB:¶Åæ$Úõßí®Å£ÇÉû¼Ã¤\ïåHÞѺA«²$¥Ðí º>6xE×uB[ÜZmÐú -å*Úo 'zÜ%!V!yÑVrFÛáâwYDÏ[î9l±Ytôè+ùwe+¥y³ã,hàwÀ߬G+Ý9YȽj¦dÊg.lÄàéîöa^>ó\ ¤uDHy²Â"÷Øà(üÁ~%»üêºÙÐ:KÙ*fYÌ.,-²¼8ËKøÕ?9£¶õe8Kd ...

在我的代码中,我尝试了很多选项:

1) 将 type: "application/octet-stream" 替换为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

2) 创建没有 s2ab 函数的 blob/文件,例如 Blob([binary_string], ...)

let binary_string = response;

// Download using blob:
let ab = s2ab(binary_string),
    blob = new Blob(
                [ab],
                type: "application/octet-stream"
            );

let downloadLink = document.createElement('a');
downloadLink.href = URL.createObjectURL(blob);
downloadLink.download = 'test-blob.xlsx';
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);

// Download using file
let FileSaver = require('file-saver'),
            ab = s2ab(binary_string),
            file = new File(
                [ab], 
                "test-file.xlsx", 
                type: "application/octet-stream");

FileSaver.saveAs(file);

// s2ab function
function s2ab(s) 
    var buf = new ArrayBuffer(s.length);
    var view = new Uint8Array(buf);
    for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
    return buf;

为什么我不能只使用 iframe 或 [下载]?因为需要授权标头。

响应中的文件是正确的,它在通过邮递员加载时打开,但是当我试图通过 XHR 响应中的 js 保存它时,它总是损坏。

非常感谢您的帮助:)

【问题讨论】:

您的 AJAX 代码丢失。 【参考方案1】:

我解决了这个问题。 在这个项目中我使用了 react,所以我使用 axios 来处理 ajax 请求。

我认为问题出在某些 axios 设置或 axios 本身;

vanilla js 上的工作代码示例:

var request = new XMLHttpRequest();
    request.open('GET', `http://localhost/api/get_xlsx`, true);
    request.setRequestHeader('Token', 'user_auth_token_needed_in_my_app');
    request.responseType = 'blob';

    request.onload = function(e) 
        if (this.status === 200) 
            var blob = this.response;
            if(window.navigator.msSaveOrOpenBlob) 
                window.navigator.msSaveBlob(blob, 'test.xlsx');
            
            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 = 'test.xlsx';
                document.body.appendChild(downloadLink);
                downloadLink.click();
                document.body.removeChild(downloadLink);
            
        
    ;
    request.send();

【讨论】:

以上是关于XLSX 客户端从后端 api 响应中保存:二进制字符串、应用程序/八位字节流的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 如何从后端读取自定义错误消息

在 EC2/Nodejs 后端 Redis/Varnish 中存储元数据和缓存 api 响应数据?

Android REST API 调用,后端没有响应新记录

如何将对象的参数从后端保存到新变量中?

如何使用节点 js 从后端 API 请求 apikey?

如何从后端向用户本地主机上的另一台服务器发出请求