接到一个新需求,从某一个服务器返回一个二进制流文件,然后要保存起来上传到另一个服务器。无需用户手动上传。
实现过程及分析过程如下:
新版本的XMLHttpRequest对象可以获取服务器端的二进制数据,方法如下:
XMLHttpRequest对象的其中一个属性responseType,是一个用于定义响应类型的枚举值。详细值如下表格所示,
而xhr另一个属性response则是返回一个 ArrayBuffer、Blob、Document,或 DOMString,具体是哪种类型取决于 XMLHttpRequest.responseType 的值。其中包含整个响应实体
值 | 数据类型 |
---|---|
‘’ | DOMString (这个是默认类型) |
arraybuffer | ArrayBuffer对象 |
blob | Blob对象 |
document | Document对象 |
json | JS 对象 , 解析得到的从服务器返回来的JSON字符串 |
text | DOMString |
一般情况下都是接收文本数据,而我们要接收服务器的二进制流文件,则需要把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也就能获取到服务器发过来的二进制流数据了。