当前位置:   article > 正文

Blob_failed to construct 'blob': the object must have a

failed to construct 'blob': the object must have a callable @@iterator prope

    Blob(Binary Large Object)术语最初来自数据库,早期数据库因为要存储声音、图片、以及可执行程序等二进制数据对象所以给该类对象取名为Blob
    在Web领域,Blob被定义为包含只读数据的类文件对象。Blob中的数据不一定是js原生数据形式。常见的File接口就继承自Blob,并扩展它用于支持用户系统的本地文件。

    构建一个Blob对象通常有三种方式:1、通过Blob对象的构造函数来构建。2、从已有的Blob对象调用slice接口切出一个新的Blob对象。3、canvas API toBlob方法,把当前绘制信息转为一个Blob对象。下面分别看看3种方式的实现:


构造函数:
var blob = new Blob(array[optional], options[optional]);

array(可选): 一个数组。数组元素可以是:ArrayBufferArrayBufferViewBlobDOMString.或者他们的组合。
options(可选): 一个对象。用于指定Blob对象的属性,可选的参数有:
type: Content-Type,用于指定将要放入Blob中的数据的类型(MIME)。


Blob对象的基本属性:

size : Blob对象包含的字节数。(只读)
type : Blob对象包含的数据类型MIME,如果类型未知则返回空字符串。


Blob对象的基本方法:
Blob.slice([start, [end, [content-type]]])

slice方法与数组的slice类似。


原生对象构建Blob


<script type="text/javascript">
window.onload = function() {
    var blob = new Blob(1234);
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

提示出错:

Uncaught TypeError: Failed to construct ‘Blob’: The 1st argument is neither an array, nor does it have indexed properties.

原因在于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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到即使是类数组对象,而数组元素类型是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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

blob.type等于application/json没问题。arg转为字符串后的长度为16加上制表符\t的宽度4个字节等于20。


slice切出一个Blob对象

window.onload = function() {
    var arg = {hello: "2016"};
    var str = JSON.stringify(arg, null, "\t");
    var blob = new Blob([str], {type: "application/json"});
    var blob2 = blob.slice();

    console.log(blob2.size);//20
    console.log(blob2.type);//""
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

可以看到,原始的Blob对象的type属性并不能传递给新的Blob对象,所以还是要自己指定。

window.onload = function() {
    var arg = {hello: "2016"};
    var str = JSON.stringify(arg, null, "\t");
    var blob = new Blob([str], {type: "application/json"});
    var blob2 = blob.slice(0, blob.size, "application/json");
    console.log(blob2.size);//20
    console.log(blob2.type);//application/json
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

canvas toBlob接口

函数原型:

void canvas.toBlob(callback, type, encoderOptions);

  • callback: 一个回调函数,新建的blob对象是唯一的参数`
  • type: 图片格式,默认为image/png,默认dpi: 96
  • encoderOptions: 0~1之间的数值。当type为image/jpeg 或 image/webp的时候,用于指定图片质量

来个DEMO:

window.onload = function() {
    var canvas = document.getElementById("main");
    canvas.toBlob(function(blob) {
        var img = document.createElement("img");         
        var url = URL.createObjectURL(blob);
        img.onload = function() {
            URL.revokeObjectURL(url);
        }
        img.src = url;
        document.body.appendChild(img);
    });
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

得出错误:

Uncaught TypeError: canvas.toBlob is not a function.

一开始觉得自己写错了,Google了下才发现Chrome居然不支持这个接口。给个polyfillCanvas toBlob


Blob基本运用

知道了Blob对象的基本属性,以及构建的方法,来看几个具体的运用。


利用Blob显示对象`


var blob = new Blob([1, 2, 3]);
var src = URL.createObjectURL(blob);
console.log(src);//blob:http%3A//localhost%3A8003/a47ea163-c253-471a-9d9e-877fe345b60f
var img = document.createElement('img');
img.onload = function() {
    URL.invokeObjectURL(img.src);
}
img.src = src;
document.body.appendChild(img);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

由于blob对象不是一个有效的文件,所以不能正常显示图片。上面的demo提到了一个URL.createObjectURL接口,顺便来学习以下:

objectURL = URL.createObjectURL(blob);

主要用于根据一个Blob对象(或者File,因为File继承自Blob),创建一个URL用于表示该对象。需要注意的是即使对同一个对象调用两次也会得到不同的URL。如果该URL不用了需要调用URL.invokeObjectURL来进行释放。浏览器会在当前document unloaded的时候自动把该URL释放。URL格式:

blob:http%3A//localhost%3A8003/a47ea163-c253-471a-9d9e-877fe345b60f

最后来看一个正常点的DEMO,利用URL.createObjectURL读取本地图片文件,并创建缩略图。


利用Blob显示缩略图`

 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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

由于File对象继承自Blob,所以我们可以很方便的利用File对象加载本地系统图片文件,并通过createObjectURL生成一个URL并加以显示。

参考文献:
+ Blob
+ Using_files_from_web

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号