Html5 文件 API - BLOB 用法?

Posted

技术标签:

【中文标题】Html5 文件 API - BLOB 用法?【英文标题】:Html5's File API - BLOB usages? 【发布时间】:2014-01-23 21:44:02 【问题描述】:

我有一个文件输入:(jsbin)

 <input type="file"   accept="image/*" id="input" multiple   onchange='handleFiles(this)' />

Which, when file selected, shows small images of the selected image:

我可以通过两种方式

使用 FileReader:

function handleFiles(t) //t=this

    var fileList = t.files;
    for (var i = 0; i < fileList.length; i++)
    
        var file = fileList[i];
        var img = document.createElement("img");
        img.style... = ...
        document.getElementById('body').appendChild(img);
        var reader = new FileReader();
        reader.onload = (function (aImg)
        
            return function (e)
            
                aImg.src = e.target.result;
            ;
        )(img);
        reader.readAsDataURL(file);
    
    // ...

使用 ObjectURL / BLOB :

 function handleFiles(t)
 
     var fileList = t.files;
     for (var i = 0; i < fileList.length; i++)
     
         var file = fileList[i];
         var img = document.createElement("img");
         img.src = window.URL.createObjectURL(file);
         img.onload = function (e)
         
             window.URL.revokeObjectURL(this.src);
         
         document.getElementById('body').appendChild(img);
     
 

如您所见,两者都有效:

但是

html结果不同:

问题:

有了第一个,我已经知道我能做什么了,它是纯 data-uri 数据。

但是我什么时候应该使用第二种方法(blob)? 我的意思是 - 我能做什么blob:http%3A//run.jsbin.com/82b29cc5-8452-4ae2-80ca-a949898f4295

附言 mdn 关于 URL.createObjectURL 的解释并不能帮助我了解何时应该使用它们。

【问题讨论】:

【参考方案1】:

blob: URL 的长度始终低于合理限制。

数据 URL 可以任意大。因此,当数据 URL 太长时,某些浏览器(IE,cough)将不再显示图像。因此,如果您想显示非常大的文件,使用blob:(或filesystem: URL)可能比数据URL 更有意义。


另外,您可以直接从blob: URL 恢复数据(前提是该 blob 尚未被撤销,例如因为文档已卸载,并且没有违反同源策略)使用XMLHttpRequest。例如,以下代码将 blob URL 的内容作为文本获取:

var blobUrl = URL.createObjectURL(new Blob(['Test'], type: 'text/plain'));
var x = new XMLHttpRequest();
// set x.responseType = 'blob' if you want to get a Blob object:
// x.responseType = 'blob';
x.onload = function() 
    alert(x.responseText);
;
x.open('get', blobUrl);
x.send();

如果您想使用XMLHttpRequest 将文件的内容提交到服务器,那么使用blob:data: URL 是没有意义的。只需使用FormData 对象直接提交File 对象即可。如果你丢失了原来的File 引用,而你只有一个blob: URL,那么你可以使用之前的sn-p 再次获取一个Blob 对象,以便在FormData 中使用。

给定一个data:-URL,恢复原始数据绝非易事。 Firefox 和 Opera 12- 允许在 XMLHttpRequest 中使用 data:-URL。 Chrome、Internet Explorer、Safari 和 Opera 15+ 拒绝通过 XMLHttpRequest 加载数据 URL。因此,在恢复数据方面,blob: URL 也优于 data:-URL。

如果您想在同一来源的不同框架中显示文件的结果,请务必使用blob: URL。如果您想在不同的框架(可能在不同的来源)中操作包含在 Blob 中的数据,不要使用 blob 或数据 URL,直接使用 postMessage 发送数据。 p>

blob:-URLs 在表示(二进制)数据方面通常比data:-URLs 更好。对于小数据(最大 20kb),data: URL 可能是更好的选择,因为支持的浏览器范围更广:比较 Can I use Blob URLs 和 Can I use Data URIs (尽管如果您正在编写复杂的 HTML5 应用程序,可能是你不会支持 IE9-).

【讨论】:

1) blob 地址是否可以跨 iframe 传输? data-uri 可以在任何东西之间转移。 blob 可以转移吗? 2) 如何查看由 blob url 表示的数据(字节)? 3) blob guid 是否有时间限制?我的意思是,如果我明天回到电脑前,再次打开浏览器,blob 是否有效? @RoyiNamir 1. 是的,在同源策略的范围内。虽然如果要在 iframe 之间传输数据,只需使用postMessage 直接传输文件即可(无需序列化数据!) 2. 使用XMLHttpRequest 查询blob:-URL 的内容。 3. 不,blob 的生命周期与文档相关,而不是时间)。它仅在卸载文档或使用URL.revokeObjectURL 时才会消失。有关 blob URL 的大量文档,请参阅 w3.org/TR/FileAPI/#url。 关于“2”:你的意思是把它上传到服务器然后调查它的数据吗? @RoyiNamir 否。请参阅我的扩展答案(回复您的后续问题)。 你可以去chat.***.com/rooms/44890/…【参考方案2】:

以下是使用这两种 URL 的主要区别:

数据 URL:

优点:

您可以非常轻松地从中获取数据 您可以将它们发送给其他用户或通过 HTTP,并且数据仍然存在 无论它们是在何处或如何创建的,只要数据有效,您就可以在任何浏览器、任何操作系统、任何地方看到内容

缺点:

数据 URL 通常过长,因此 IE 可能无法处理它们,并且在任何浏览器中处理都会很烦人 它们比 BLOB URL 效率低(您必须读取文件来创建它,您不需要使用 BLOB 等)

BLOB 网址:

优点:

它们比数据 URL 短得多,因此更易于管理 您可以访问他们的数据,但由于 URL 只是对数据的不透明引用,因此必须使用 FileReader 访问数据,并且不能直接从 URL 中提取数据,如数据 URL 因为它们有一个合理的长度,所以它们更容易处理并且有更好的IE支持

缺点:

无法在 URL 本身中访问数据(该 URL 是一个不透明的引用)并且它不存储在云中 由于 con #1,您无法将 URL 发送到服务器/其他用户,因为他们将无法访问数据。因此,该 URL 仅供您使用。 您也无法在不同的浏览器中访问来自 BLOB URL 的数据(即使在同一台机器上) 此外,即使在同一个浏览器上,您也无法从不同的来源访问 BLOB URL

这个列表看起来数据 URL 是一个明显的优势,但 BLOB url 的创建速度更快,并且,除非您需要将 url 发送给其他用户或服务器,否则您应该使用它们,因为它们更快,更易于使用、更易于管理且更适合 IE。但是,如果您确实需要向服务器或其他用户发送 url,我建议以某种方式直接使用 XHR2 传输 blob。数据网址不是那么好。

【讨论】:

我不相信你列出的优缺点。 blob/data URL 通常用于向用户提供文件下载和/或在媒体元素(例如&lt;img&gt;)中显示数据,而不是用于将数据传输到另一个网站或页面。要与其他帧共享数据,您通常会发布原始缓冲区本身。将 blob 序列化为数据 URL 效率非常低:需要 FileReader 将 blob 转换为数据 URL。如果接收者想再次使用数据,那么手动解析 URL(使用atob 和字符串操作函数)是获取 blob 的最糟糕的方法。 [...] [...] 要将数据发布到服务器,您可以使用 FormData 对象以最小的开销发送 File/Blob 对象(与数据 URL,base64 编码相反显着增加数据大小)。由于我们都认为 blob: URL 通常是现代浏览器中的最佳选择,因此我将继续讨论 blob URL 的缺点。如前所述,您通常不会将 URL 发送给其他方,而是发送数据。如果您不再拥有原始数据,可以使用 XHR 再次获取 Blob。就像 blob: URLs 一样,data-URLs 也不能通过 XHR 恢复(IE、Chrome、Safari、Opera 15+)。

以上是关于Html5 文件 API - BLOB 用法?的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 FileReader读取Blob对象API详解

前端读取Excel报表文件

当我使用 html5 将数据上传到服务器时,我可以在 blob 数据中设置文件名吗?

如何将 Blob 写入本地文件? [复制]

HTML5中的Blob对象的使用

前端上传大型文件或超长数据的解决办法