什么是Blob URL,为什么要使用它?


348

Blob URL出现很多问题。

src在YouTube上搜索了一个视频标签,发现该视频src就像:

src="blob:https://crap.crap"

我打开了src视频中的Blob URL,该URL 出现错误。我无法打开链接,但是它正在使用src标记。这怎么可能?

要求:

  • 什么是Blob URL?
  • 为什么使用它?
  • 我可以在服务器上创建自己的Blob URL吗?
  • 如果您还有其他详细信息


3
本质上不允许热链接。(如youtube)
facepalm42

Answers:


349

Blob URL(参考W3C,正式名称)或Object-URL(参考MDN和方法名称)与BlobFile对象一起使用。

src =“ blob:https://crap.crap ”我打开了视频src中的blob网址,它给出了一个错误,但我无法打开,但是正在使用src标签,这怎么可能?

Blob URL只能由浏览器在内部生成。URL.createObjectURL()将创建对Blob或File对象的特殊引用,以后可以使用释放该对象URL.revokeObjectURL()。这些URL只能在浏览器的单个实例中和同一会话(即页面/文档的生命周期)中本地使用。

什么是Blob网址?
为什么使用它?

Blob URL /对象URL是一种伪协议,允许将Blob和File对象用作图像,下载二进制数据链接等内容的URL源。

例如,您不能处理Image对象的原始字节数据,因为它不知道如何处理它。例如,它要求通过URL加载图像(二进制数据)。这适用于任何需要URL作为源的内容。而不是上传二进制数据,而是通过URL将其提供回来,最好使用额外的本地步骤,以便无需通过服务器即可直接访问数据。

这也是Data-URI(编码为Base-64的字符串)的更好替代方案。Data-URI的问题在于JavaScript中每个字符占用两个字节。最重要的是,由于使用Base-64编码,因此添加了33%。Blob是纯二进制字节数组,没有Data-URI那样有任何明显的开销,这使它们处理起来更快,更小。

我可以在服务器上创建自己的Blob网址吗?

不,只能在浏览器内部创建Blob URL /对象URL。您可以通过文件读取器API来创建Blob并获取File对象,尽管BLOB只是表示Binary Large OBject,并存储为字节数组。客户端可以请求将数据作为ArrayBuffer或Blob发送。服务器应将数据作为纯二进制数据发送。数据库通常也使用Blob来描述二进制对象,从本质上讲,我们基本上是在谈论字节数组。

如果您还有其他详细信息

您需要将二进制数据封装为BLOB对象,然后用于URL.createObjectURL()为其生成本地URL:

var blob = new Blob([arrayBufferWithPNG], {type: "image/png"}),
    url = URL.createObjectURL(blob),
    img = new Image();

img.onload = function() {
    URL.revokeObjectURL(this.src);     // clean-up memory
    document.body.appendChild(this);   // add image to DOM
}

img.src = url;                         // can now "stream" the bytes

请注意,URL可能会在webkit-browsers中添加前缀,因此请使用:

var url = (URL || webkitURL).createObjectURL(...);

19
在过去的6个小时中,我一直在尝试使PHP将从AJAX传递的对象URL转换为图像文件。直到我读完您的解释后,我才意识到为什么它没有向文件中写入任何数据。您的简洁透彻的解释消除了我的痛苦。谢谢。
Partack '17

4
@ K3N是否可以获取Blob URL的真实来源,而不是生成的URL?鸟巢凸轮产生斑点URL阻止人们记录自己的相机
亚历Kwitny

4
对我的启示“ BLOB只是意味着二进制大对象”
canbax

6
是否可以检索Blob /文件对象的内容并下载其内容(图像或视频)?
DFSFOT

4
这可能与想知道如何下载Blob视频的人们有关:stackoverflow.com/q/42901942/1530508
ApproachingDarknessFish

10

该Javascript函数旨在显示Blob File API和Data API 之间的区别,以便在客户端浏览器中下载JSON文件:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @author Loreto Parisi
 */

var saveAsFile = function(fileName, fileContents) {
    if (typeof(Blob) != 'undefined') { // Alternative 1: using Blob
        var textFileAsBlob = new Blob([fileContents], {type: 'text/plain'});
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        } else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else { // Alternative 2: using Data
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' +
            encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
} // saveAsFile

/* Example */
var jsonObject = {"name": "John", "age": 30, "car": null};
saveAsFile('out.json', JSON.stringify(jsonObject, null, 2));

该函数称为like saveAsFile('out.json', jsonString);。它将创建一个被浏览器立即识别的ByteStream,该浏览器将直接使用File API下载生成的文件URL.createObjectURL

在中else,可以看到通过href元素加上Data API 获得的相同结果,但这具有Blob API没有的一些限制。


1
您可以修改此设置以保存来自推文的视频吗?
造成逻辑断

3

什么是Blob网址?为什么使用它?

BLOB只是字节序列。浏览器将其识别为字节流。它用于从源获取字节流。

Blob对象代表不可变的原始数据的类似文件的对象。Blob表示的数据不一定是JavaScript原生格式。File接口基于Blob,继承了Blob功能并将其扩展为支持用户系统上的文件。

我可以在服务器上创建自己的Blob网址吗?

是的,您可以通过多种方法来执行此操作,例如,尝试http://php.net/manual/en/function.ibase-blob-echo.php

阅读更多


2
使用BLOB网址可以获得任何好处吗?
Waqas Tahir 2015年

你可以阅读这个来得到答案。显然有优点和缺点。
罗伯特·

4
您正在将对象URL与BLOB混合在一起。Object-URL是一种伪协议,允许BLOB用作URI源。

4
这个答案有一些明显的缺陷。主要是在先前的评论中指出,一些非常不同的概念混合了……然后被压缩为一个不完整且不正确的答案。
trs

2

我修改了工作解决方案,以处理两种情况..当视频上传时和图像上传时..希望对您有所帮助。

的HTML

<input type="file" id="fileInput">
<div> duration: <span id='sp'></span><div>

Java脚本

var fileEl = document.querySelector("input");

fileEl.onchange = function(e) {


    var file = e.target.files[0]; // selected file

    if (!file) {
        console.log("nothing here");
        return;
    }

    console.log(file);
    console.log('file.size-' + file.size);
    console.log('file.type-' + file.type);
    console.log('file.acutalName-' + file.name);

    let start = performance.now();

    var mime = file.type, // store mime for later
        rd = new FileReader(); // create a FileReader

    if (/video/.test(mime)) {

        rd.onload = function(e) { // when file has read:


            var blob = new Blob([e.target.result], {
                    type: mime
                }), // create a blob of buffer
                url = (URL || webkitURL).createObjectURL(blob), // create o-URL of blob
                video = document.createElement("video"); // create video element
            //console.log(blob);
            video.preload = "metadata"; // preload setting

            video.addEventListener("loadedmetadata", function() { // when enough data loads
                console.log('video.duration-' + video.duration);
                console.log('video.videoHeight-' + video.videoHeight);
                console.log('video.videoWidth-' + video.videoWidth);
                //document.querySelector("div")
                //  .innerHTML = "Duration: " + video.duration + "s" + " <br>Height: " + video.videoHeight; // show duration
                (URL || webkitURL).revokeObjectURL(url); // clean up

                console.log(start - performance.now());
                // ... continue from here ...

            });
            video.src = url; // start video load
        };
    } else if (/image/.test(mime)) {
        rd.onload = function(e) {

            var blob = new Blob([e.target.result], {
                    type: mime
                }),
                url = URL.createObjectURL(blob),
                img = new Image();

            img.onload = function() {
                console.log('iamge');
                console.dir('this.height-' + this.height);
                console.dir('this.width-' + this.width);
                URL.revokeObjectURL(this.src); // clean-up memory
                console.log(start - performance.now()); // add image to DOM
            }

            img.src = url;

        };
    }

    var chunk = file.slice(0, 1024 * 1024 * 10); // .5MB
    rd.readAsArrayBuffer(chunk); // read file object

};

jsFiddle网址

https://jsfiddle.net/PratapDessai/0sp3b159/


1.代码缩进的目的是什么?其他人都使用缩进突出代码的逻辑结构。2.您的JSFiddle不执行任何操作。我试图上传图片和视频。
7vujy0f0hy19年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.