js 接收服务器返回的二进制流文件,保存并转成文件

771 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情
接到一个新需求,从某一个服务器返回一个二进制流文件,然后要保存起来上传到另一个服务器。无需用户手动上传。
实现过程及分析过程如下:
新版本的XMLHttpRequest对象可以获取服务器端的二进制数据,方法如下:
XMLHttpRequest对象的其中一个属性responseType,是一个用于定义响应类型的枚举值。详细值如下表格所示,
而xhr另一个属性response则是返回一个 ArrayBuffer、Blob、Document,或 DOMString,具体是哪种类型取决于 XMLHttpRequest.responseType 的值。其中包含整个响应实体

数据类型
‘’DOMString (这个是默认类型)
arraybufferArrayBuffer对象
blobBlob对象
documentDocument对象
jsonJS 对象 , 解析得到的从服务器返回来的JSON字符串
textDOMString

一般情况下都是接收文本数据,而我们要接收服务器的二进制流文件,则需要把responseType定义为blob类型。如下

  var xhr = new XMLHttpRequest();
 xhr.open('GET', URL,true);
 xhr.responseType = 'blob';

接收数据则需要使用浏览器自带的Blob对象进行接收。

var blob = new Blob([xhr.response]);

这就完成了接收工作,下一步就是把bolb数据转成文件,key.DSP为文件名

var file = new window.File([blob], 'key.DSP', {type: 'blob'}),

那么最后就可以根据自己拿到的文件完成业务代码即可

  var fd = new FormData();
  fd.append("file",file);
  updateFile(fd);//上传文件
  Download(xhr.response,'key.DSP');//下载文件(当然直接访问服务器返回的二进制流文件即可成功下载

如果是下载该文件,可通过以下方法实现:

function Download(content, filename) {
    var eleLink = document.createElement('a');
    eleLink.download = filename;
    eleLink.style.display = 'none';
    // 字符内容转变成blob地址
    var blob = new Blob([content]);
    eleLink.href = URL.createObjectURL(blob);
    // 触发点击
    document.body.appendChild(eleLink);
    eleLink.click();
    // 然后移除
    document.body.removeChild(eleLink);
};

附上开发该需求的过程中遇到的一个问题,当然不是很常用,一般情况下,我们都是发起异步请求。当时,当我们把xhr.open('GET', URL,true)的第三个参数设置为false的时候,表示请求是同步的。
当XMLHttpRequest不是异步(即同步)时,responseType属性不能设置。因此不能采用以上方法,则需要使用以下方法。

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, false); 
    xhr.overrideMimeType("text/plain; charset=x-user-defined");
    xhr.send(null);
    
    var data;
    if (xhr.status === 200) {
        data = stringToArrayBuffer(xhr.response);
    } 
    
    // ...
    
    function stringToArrayBuffer(str) {
        var buf = new ArrayBuffer(str.length);
        var bufView = new Uint8Array(buf);
    
        for (var i=0, strLen=str.length; i<strLen; i++) {
            bufView[i] = str.charCodeAt(i);
        }
    
        return buf;
    }

这样data也就能获取到服务器发过来的二进制流数据了。