从这系列的以上文章中,你已经学到以传统的方式使用文件。你可以上传文件到服务器,可以从硬盘中读取文件。这些都是最普遍的操作文件的方式。然而,还有一个全新的方式让你能简化任务,就是使用 URL 对象。

何为 URL对象?

URL对象是硬盘上指向文件的URL。例如,你想在页面上显示用户系统里的一张图片,服务器不必知道对应文件,当然也不用上传它。你只需在页面中加载它即可。是的,前面的文章中提到,获取文件的引用,读取 data URI,然后赋值给一个 <img> 元素。不过细想其中多浪费:图片原本就在硬盘上,还要转换成另一个格式再用之?如果你创建一个URL对象,你可以直接赋值给 <img> 元素而后直接加载文件。

它是如何工作的?

File API[1] 定义了一个全局的 URL 对象其有两个方法 。 createObjectURL()方法,是接收一个文件的引用返回一个URL对象。这是通知浏览器来创建和管理一个URL来加载文件。 revokeObjectURL()方法,则是销毁创建的URL,有效果释放内存。当然,所有的URL对象将在浏览器重新载入时全部被销毁,也有助于释放它们占用的内存。

要支持URL 对象目前并没有像File API 的其他部分一样乐观。写此文的时候IE 10+ 和 Firefox 9+ 都支持全局 URL 对象。Chrome 则支持webkitURL, Safari 和Opera 尚未支持。

实例

那么,你如何不读取图片硬盘上的资源就直接显示呢?假设你有一种方式让用户选择了文件,然后你就有了文件的引用并保存到变量file中,然后你就可以使用下面的方法了:

var URL = window.URL || window.webkitURL,
    imageUrl,
    image;

if (URL) {
    imageUrl = URL.createObjectURL(file);
    image = document.createElement("img");

    image.onload = function() {
        URL.revokeObjectURL(imageUrl);
    };

    image.src = imageUrl;
    document.body.appendChild(image);
}

本例的 URL 变量是原生浏览器对象的一个引用,假设浏览器支持URL对象,URL通过file创建一个对象赋值给imageUrl变量。<img> 元素的onload 事件触发后将销毁URL 对象(一分钟内),接着,给src属性赋值后将<img>追加到页面上(你也可以使用一个页面上已有的<img>元素的)。

为什么要在图片加载完成后销毁URL对象呢?因为图片载入后URL对象已经无用了,如果还要用于其他元素则可以保留。本例中只用于一个<img>元素,没有其他用途了,所以图片加载完销毁它是最佳内存释放时机。

安全和其他问题

乍一看,这个功能有点可怕。事实上你是通过一个URL从用户的硬盘上加载的文件。没错,显然这个功能有安全隐患。URL由于是浏览动态产生的本身安全问题不大而且在其他电脑上无效。但是跨源(cross-origin)呢?

File API 禁止不同源上使用URL对象。当创建一个URL后,它与执行JS的页面已经绑定,因此你不能将www.wrox.com 上的URL对象应用到p2p.wrox.com (会报错)上。 不过,两个来自 www.wrox.com的页面,如果一个页面通过iframe被嵌在另一个页面中,则可以共享URL对象。

URL对象的生命周期取决于页面,页面卸载后就会被销毁,因此,通过data storage将URL对象是没法保存在客户端供今后使用的,页面卸载后都被销毁掉的。

当你使用URL对象时,浏览器会发出一个GET请求,类似于images, scripts, web workers, style sheets, audio, video。你是没法使用URL对象的同时让浏览器发出POST请求的。比如<form> 设置method 成 “post”的效果.

下期预告

创建URL对象来连接到本地文件是非常强大的功能。比起读到本的文件然后保存到JS里再显示到页面上,你已可以轻松的创建一个URL直接指向它即可。但是,用JS操作文件只是刚刚开始,下篇文章你将会学到其他有趣的方法来操作文件的数据。

参考资料

  1. File API

Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox PublishingO’Reilly Publishing, or anyone else. I speak only for myself, not for them.

原文