我经常被问到的一个问题是,为什么 Firefox 不支持文件系统 API。通常,但并不总是,他们特别指的是 FileSystem 和 FileWriter 规范,Google 在 Chrome 中实现了这些规范,并已提议在 W3C 中进行标准化。
答案有些复杂,很大程度上取决于人们实际想要使用上述两个规范的哪些具体功能。这些规范相当庞大,功能齐全,因此人们想要用它做很多不同的事情并不令人惊讶。这篇博文试图给出我对此问题的答案,并解释为什么我们没有实现上述两个规范。但请注意,这篇博文代表我个人的观点,旨在引发更多关于此主题的讨论。
如上所述,在 Firefox 中要求“文件系统 API 支持”的人实际上往往对解决许多不同的问题感兴趣。我认为大多数,但到目前为止还不是全部,这些问题都有比文件系统 API 更好的解决方案。因此,让我在下面逐步介绍它们。
本地存储资源
可能最常见的用途是简单地存储一组资源,以便它们可以离线使用,而无需使用网络。如果您需要快速访问这些资源,或者即使用户离线也可以访问它们,这将非常有用。游戏是需要此功能的非常常见的应用程序类型。例如,一艘敌人的宇宙飞船可能与一些相关的图像以及一些相关的音频相关联,这些音频在敌人四处移动并射击时使用。今天,人们通常通过将图像和音频文件存储在文件系统中,然后将这些文件的名称与敌人的速度和火力等信息一起存储来解决这个问题。
但是,在我看来,将一些数据与其他数据分开存储似乎不是最佳的方案。尤其是在存在可以同时存储结构化数据和文件数据的解决方案的情况下。IndexedDB 将文件数据视为任何其他类型的数据。您可以将 File
或 Blob
写入 IndexedDB,就像您可以存储字符串、数字和 JavaScript 对象一样。这是由 IndexedDB 规范规定的,到目前为止已在 Firefox 和 IE 的 IndexedDB 实现中实现。使用这种方式,您可以将所有需要的信息存储在一个地方,并且对 IndexedDB 的单个查询可以返回您需要的所有数据。例如,如果您正在构建一个基于 Web 的电子邮件客户端,您可以存储类似以下的对象:
{
subject: "Hi there",
body: "Hi Sven,\nHow are you doing...",
attachments: [blob1, blob2, blob3]
}
这里另一个优势是,无需为资源创建文件名。只需存储 File
或 Blob
对象即可。无需名称。
在 Firefox 的 IndexedDB 实现中(我相信 IE 的实现也是如此),文件是透明地存储在实际数据库之外的。这意味着将文件存储在 IndexedDB 中的性能与将文件存储在文件系统中一样好。它不会使数据库本身膨胀从而减慢其他操作的速度,从文件中读取意味着实现只会从操作系统文件读取,因此它与文件系统一样快。
Firefox IndexedDB 实现甚至足够智能,如果您在 IndexedDB 数据库中存储了多个文件的同一个 Blob,它只会创建该文件的一个副本。对同一个 Blob 的进一步引用只会增加一个内部引用计数。这对网页来说是完全透明的,它唯一会注意到的就是更快的写入速度和更少的资源使用。但是,我不确定 IE 是否也这样做,因此在依赖它之前请先检查一下。
访问图片和音乐文件夹
人们询问与文件系统 API 相关的第二件事是能够访问用户的图片或音乐库等内容。这是提交给 W3C 的文件系统 API 实际上没有提供的功能,尽管许多人似乎认为它确实提供了。为了满足这种用例,我们拥有 设备存储 API。此 API 允许对“用户文件”进行完整的文件系统功能。即,不是特定于网站的文件,而是由用户管理和拥有的资源,用户可能希望通过多个应用程序访问这些资源。例如照片和音乐。设备存储 API 基本上是一个简单文件系统 API,主要针对这些类型的文件进行了优化。
我们仍在指定和实现此 API。它可以在最新的 nightly 版本中进行测试,但到目前为止尚未默认启用。向 Web 公开此功能的主要问题是安全性。您不希望任何网站读取或修改您的图像。我们可以像使用 GeoLocation API 一样弹出一个提示,考虑到此 API 可能会删除您过去十年来的所有图片,我们可能想要更多。这是我们正在积极努力的事情。但在这里,安全性绝对是难点,而不是实现低级文件操作。
低级文件操作
一个不太常见的请求是能够进行低级创建、读取、更新和删除 (CRUD) 文件操作。例如,能够在 10MB 文件的中间写入 10 个字节。这不是 IndexedDB 目前支持的功能,它只允许添加和删除整个文件。FileWriter 规范草案支持这一点。但是,我认为此 API 的这部分存在一些非常基本的问题。具体来说,它没有锁定功能,因此无法执行多个文件操作并确保另一个选项卡没有在这些操作之间修改或读取文件。也没有办法进行 fsync,这意味着您无法在 FileWriter 之上实现 ACID 类型应用程序,例如数据库。
相反,我们创建了一个具有相同目标的 API,但它具有锁定文件和执行多个操作的功能。这以一种方式完成,以确保没有页面忘记解锁文件或出现死锁的风险。该 API 还允许 fsync 操作,这应该能够在 FileHandle 之上实现像数据库这样的东西。但最重要的是,该 API 的设计方式可以确保您不必像使用 FileWriter 那样嵌套异步回调。换句话说,它应该更容易让作者使用。您可以在以下位置了解更多关于 FileHandle 的信息:
https://wiki.mozilla.org/WebAPI/FileHandleAPI
filesystem
URL 方案
文件系统 API 中还存在一种上述未涵盖的功能。该规范引入了一种新的 filesystem:
URL 方案。从 filesystem:
加载 URL 时,它会返回使用文件系统 API 存储的文件的内容。这对于几个原因来说是一个非常酷的功能。首先,这些 URL 是可预测的。将文件存储在文件系统中后,您始终知道可以使用哪个 URL 从中加载。并且只要文件存储在文件系统中,即使网页重新加载,该 URL 也会继续工作。其次,相对 URL 与 filesystem:
方案一起使用。因此,您可以从存储在文件系统中的一个资源创建指向存储在文件系统中的另一个资源的 链接。
Firefox 支持 blob:
URL 方案,它允许在可以使用 URL 的任何地方从 Blob 加载数据。但是它没有上述功能。这是我真正想找到解决方案的地方。如果我们找不到更好的解决方案,那么实现 Google 规范绝对是一个选择。
结论
与往常一样,在讨论要添加到 Web 平台的功能时,重要的是讨论用例和功能,而不是直接跳到特定的解决方案。文件系统 API 旨在解决的大多数用例都可以通过其他方式解决。我认为,很多时候是通过更好的方式。
这就是为什么我们没有优先考虑实现文件系统 API,而是专注于让我们的 IndexedDB 实现变得出色,并想出一个用于低级文件操作的良好 API。
专注于 IndexedDB 也意味着我们很快将在 3 个浏览器中提供一个用于基本文件存储的良好 API:IE10、Firefox 和 Chrome。
相关的是,我们刚刚修复了 IndexedDB 实现中最后一个已知的规范合规性问题,因此 Firefox 16 将以非前缀形式发布 IndexedDB!
与往常一样,我们非常乐意收到其他人的反馈,尤其是来自 Web 开发者的反馈。您认为我们是否应该优先考虑文件系统 API?如果是,为什么?
关于 Jonas Sicking
Jonas 在 Web 浏览器领域从事开发工作已超过十年。他从 2000 年开始作为开源贡献者,为新开源的 Mozilla 项目做贡献。2005 年,他全职加入 Mozilla,此后一直在从事 DOM 和 Web 平台的其他部分的开发工作。他现在是 Mozilla Web API 项目的技术主管,也是 W3C IndexedDB 和文件 API 规范的编辑。
117 条评论