Blob(Binary Large Object)术语最初来自数据库(oracle 中也有类似的栏位类型。),早期数据库因为要存储声音、图片、以及可执行程序等二进制数据对象所以给该类对象取名为Blob。
在Web领域,Blob被定义为包含只读数据的类文件对象。Blob中的数据不一定是js原生数据形式。常见的File接口就继承自Blob,并扩展它用于支持用户系统的本地文件。
var blob = new Blob(array[optional], options[optional]);
构造函数,接受两个参数
第一个参数:为一个数据序列,可以是任意格式的值,例如,任意数量的字符串,Blobs 以及 ArrayBuffers。
第二个参数:用于指定将要放入Blob中的数据的类型(MIME)(后端可以通过枚举MimeType,获取对应类型:
MimeType mimeType = MimeType.toEnum(file.getContentType());)。
<script>
var blob = new Blob(["Hello World!"],{type:"text/plain"});
</script>
Blob对象的基本属性:
size :Blob对象包含的字节数。(只读)
type : Blob对象包含的数据类型MIME,如果类型未知则返回空字符串。
原生对象构建Blob
<script type="text/javascript">
window.onload = function() {
var blob = new Blob(1234);
}
</script>
原因在于Blob构造函数要求第一个参数必须是数组,而这里第一个参数既不是一个数组,也没有可索引的属性。既然这里提到了对象的可索引属性,让我联想到了类数组的概念,而Arguments就是一个很好的例子。来试一试:
<script type="text/javascript">
function testArgumentsBlob() {
var blob = new Blob(arguments);
console.log(blob.size);//3
console.log(blob.type);//""
}
window.onload = function() {
testArgumentsBlob(1, 2, 3);
}
</script>
可以看到即使是类数组对象,而数组元素类型是Number也能得出正确的结论,猜想大概是由于构造函数内部把Number转化为String的缘故吧!
再来试一试其他的参数类型:
window.onload = function() {
var arg = {hello: "2016"};
var blob = new Blob([JSON.stringify(arg, null, "\t")], {type: "application/json"});
console.log(blob.type);//application/json
console.log(blob.size);//20
}
blob.type等于application/json没问题。arg转为字符串后的长度为16加上制表符\t的宽度4个字节等于20。
Blob对象的基本方法:
大文件分割 (slice() 方法),slice方法与数组的slice类似。Blob.slice([start, [end, [content-type]]])
ice() 方法接受三个参数,起始偏移量,结束偏移量,还有可选的 mime 类型。如果 mime 类型,没有设置,那么新的 Blob 对象的 mime 类型和父级一样。
当要上传大文件的时候,此方法非常有用,可以将大文件分割分段,然后各自上传,因为分割之后的 Blob 对象和原始的是独立存在的。
不过目前浏览器实现此方法还没有统一,火狐使用的是 mozSlice() ,Chrome 使用的是 webkitSlice() ,其他浏览器则正常的方式 slice()
可以写一个兼容各浏览器的方法:
function sliceBlob(blob, start, end, type) {
type = type || blob.type;
if (blob.mozSlice) {
return blob.mozSlice(start, end, type);
} else if (blob.webkitSlice) {
return blob.webkitSlice(start, end type);
} else {
throw new Error("This doesn't work!");
}
}
var input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.multiple = true;
input.style.display = "none";
document.body.appendChild(input);
var fileSelect = document.createElement("a");
fileSelect.href = "#";
fileSelect.appendChild(document.createTextNode("Choose files"));
document.body.appendChild(fileSelect);
var imgList = document.createElement("div");
imgList.innerHTML = "<p>No file Selected!</p>"
document.body.appendChild(imgList);
input.addEventListener("change", function(e) {
var files = this.files;
if(!files.length) {
return;
}
imgList.innerHTML = "";
var list = document.createElement("ul");
imgList.appendChild(list);
for(var i = 0; i < files.length; i++) {
var li = document.createElement("li");
list.appendChild(li);
var img = document.createElement("img");
img.src = window.URL.createObjectURL(files[i]);
img.height = 60;
img.width = 60;
img.onload = function() {
window.URL.revokeObjectURL(this.src);
}
li.appendChild(img);
var info = document.createElement("span");
info.innerHTML = files[i].name + ":" + files[i].size + " bytes";
li.appendChild(info);
}
}, false);
fileSelect.addEventListener("click", function(e) {
input.click();
e.preventDefault();
}, false);
用到
export function fileDownload(id, fileName,suffix) {
downloadFileById(id).then(res => {
let link = document.createElement("a");
if(suffix) {
link.href = window.URL.createObjectURL(new Blob([res],{type:"text/"+suffix}));
}else {
link.href = window.URL.createObjectURL(new Blob([res]));
}
link.target = "_blank";
console.log(fileName)
link.download = fileName;
document.body.appendChild(link); // Firefox 中必须这么写,不然不会起效果
link.click();
document.body.removeChild(link);
});
}