HTML5 文件 API:功能和兼容性
通过代码演示深入探讨 HTML5 File API 的功能以及与不同 Web 浏览器的兼容性。
引言
HTML5 File API 用于通过 Web 浏览器访问客户端机器上的文件。HTML5 标准中包含 3 个级别的 File API:
- File API(我称之为 File Reader API)
- File API: Writer(也称为 File Writer API)
- File API: Directories and System(也称为 File System API)
我花了一些时间分析每个级别的功能以及与不同 Web 浏览器的兼容性。这有助于为我未来可能需要访问客户端本地文件的 Web 应用程序开发选择技术,例如文件上传和下载。
实验浏览器
我选择了以下 Web 浏览器作为实验浏览器。在进行研究时,它们都处于最新版本。
- Microsoft Internet Explorer 10
- Google Chrome 30
- Mozilla Firefox 24
- Safari 6 (Mac OS 和 iOS 7)
注意:Safari 5.1.7 是 Windows 的最后一个版本。Apple 从 Safari 6 开始终止对 Windows 的支持。Safari 5.1.7 不支持 File API。换句话说,当我们在 Windows 上使用 Safari 时,我们无法使用 File API。
演示代码
演示代码文件位于 VS 2012 Web 应用程序中。它包含以下文件
- FileReadApi.html:演示读取小文件或大文件并显示进度。还支持停止和恢复。此演示可以在所有先前列出的浏览器中运行。
- FileSaver.html:演示如何实现和使用
FileSaver
。 此演示可以在所有先前列出的浏览器中运行。 - FileSystemApi.html:演示如何使用 File System API 和
FileWriter
。它仅在先前列出的浏览器中的 Chrome 中可用。 - FileSystemApiConsumer.html:列出在 FileSystemApi.html 中创建的所有文件,并读取用户指定的文件。仅适用于 Chrome。
- DownloadFileViaBrowser.html 和 DownloadHandler.ashx:演示启用浏览器下载功能而无需暴露服务器上文件位置的服务器代码。此演示几乎可以在所有浏览器中运行。
文件读取器 API
有关标准详情,请参阅 http://www.w3.org/TR/FileAPI/。
功能
使用文件读取器 API,我们可以:
- 获取一个或多个文件对象(
File
接口的实例),客户端通过弹出的打开文件对话框(<input type=”file”/>
)选择这些文件对象。任何进一步的文件操作都必须在这些文件对象上进行。 - 只读取文件对象的以下信息:
- 不带路径的名称。
- MIME 类型。
- 大小(以字节为单位)。实时更新。
- 最后修改日期和时间。实时更新。
- 读取文件数据,从任何字节位置读出和写入(通过
FileReader
接口)。这可以帮助我们实现中断和恢复上传。 - 支持 RWW(边写边读:读取一个仍在被其他程序写入的文件,该程序已将文件共享模式设置为读取)。
限制
文件读取器 API 具有以下限制:
- 仅适用于客户端通过弹出的打开文件对话框明确选择的文件。即使我们知道完整的文件路径,也无法打开文件。
- 无法监控文件是否被删除。因此,我们无法在 RWW 场景中监控标志文件。
有一件有趣的事情。我试图找到一种解决方法来监控文件删除。我计划的步骤是:
- 让客户端明确选择现有标志文件,以便我可以获取标志文件对象。
- 让我的代码定期获取标志文件大小、最后修改日期并读取第一个字节。如果发生一些奇怪的事情,例如文件未找到异常,我可以说标志文件已被删除。
然而,我发现在我的实验中,不同浏览器的行为差异很大:
- Firefox:抛出文件未找到异常。非常好!
- Chrome:没有异常,最后修改日期一直变为当前时间。奇怪!
- IE 10:没有异常,信息没有变化。非常奇怪!
- Safari:未测试。
实验表明,计划的解决方法无法在所有浏览器中运行。我认为这是因为 HTML5 File API 标准没有明确说明如何处理此类错误。所以我不得不放弃解决方法计划。
浏览器支持
所有我们的实验浏览器都支持文件读取器 API。
文件写入器 API
有关标准详情,请参阅 http://www.w3.org/TR/file-writer-api/。
功能
使用文件写入器 API,我们可以:
- 将一个 blob 保存为客户端通过弹出的保存文件对话框指定的文件(通过
saveAs
函数和FileSaver
接口)。如果文件存在,它将被覆盖。 - 在 Sandbox 中,将多个 blob 写入单个文件中的任何字节位置(
FileWriter
接口)。
有关 Sandbox 的更多信息,请参阅 File System API 章。
限制
文件写入器 API 具有以下限制:
- 使用
FileSaver
写入文件时,只允许一个 blob。这意味着我们无法将从 Internet 连续接收到的多个数据块写入文件。等待所有块到达然后构建一个巨大的 blob 是不可行的。blob 大小限制由客户端机器的硬件容量决定,因此找出既安全又尽可能大的数字是不可能和没有意义的。无论如何,写入小文件(可能 <= 10MB)是可以的。 - 在客户端上的 blob 中所有数据准备好之前,
FileSaver
不会写入文件。这意味着在写入完成之前,其他程序无法读取客户端上的文件。 FileWriter
仅在 Sandbox 中可用。实际上,标准说它可能被移至 File System API。- 不支持删除文件.
注意:尽管 BlobBuilder
和 FileSaver
在标准中,但它们已被所有浏览器供应商弃用。相反,我们需要直接构造 Blob
并实现我们自己的 FileSaver
或使用第三方实现。
浏览器支持
所有我们的实验浏览器都支持我们自己的 FileSaver
实现。
Chrome 是唯一支持 FileWriter
的浏览器。
文件系统 API
有关标准详情,请参阅 http://www.w3.org/TR/file-system-api/。
功能
使用文件系统 API,我们可以:
- 创建 Sandbox 作为私有文件系统(使用
requestFileSystem
函数)。 - Sandbox 没有大小限制。唯一的限制是硬盘容量。
- 在 Sandbox 中执行所有与目录相关的操作,包括创建、重命名、删除、复制、移动等。
- 在 Sandbox 中执行所有与文件相关的操作,包括创建、重命名、读取、写入、删除、复制、移动等。
限制
文件系统 API 只能在应用程序隔离的 Sandbox 中使用。应用程序通过协议、地址和端口的组合进行区分。例如,“https://codeproject.org.cn”、“https://codeproject.org.cn”、“https://codeproject.org.cn:8080”和“http://us.codeproject.com”都是不同的应用程序;“https://codeproject.org.cn/my/default.aspx”和“https://codeproject.org.cn/api/data/”在同一个应用程序中。
因此,文件系统 API 具有以下限制:
- 一个应用程序 Sandbox 中的项目对其他应用程序不可见。
- Sandbox 中的项目对其他类型的 Web 浏览器不可见。例如,在 Google Chrome 中创建的 Sandbox 对其他非 Chrome 浏览器不可见。
- Sandbox 中的项目对非浏览器程序不可见。
注意:借助文件读取器 API 和文件写入器 API,仍然可以在 Sandbox 和客户端文件系统之间复制文件。
浏览器支持
在我们的实验浏览器中,Chrome 是唯一支持文件系统 API 的浏览器。没有其他浏览器供应商保证将来会实现它。事实上,它未能获得浏览器供应商的关注,并且仅在一些基于 Webkit 的浏览器中受支持。
以下截图显示了 Firefox 在 http://html5test.com 上的测试结果。请注意中央的斜体注释。
相关主题
通过 Web 浏览器下载
我们需要 FileSaver
或 File Writer API 的原因之一是启用特殊的文件下载逻辑。如果没有 Flash、Silverlight 或 ActiveX 等任何插件,Web 浏览器中下载文件的最佳方法是使用浏览器内置的下载功能。 此功能可以
- 涵盖
FileSaver
的所有功能。 - 将文件下载到浏览器的默认下载文件夹或客户端在弹出的保存文件对话框中指定的任何其他文件夹。客户端可以通过浏览器设置选择喜欢的方式。
- 客户端可以选择是否在下载后打开文件。
- HTTP 协议支持下载文件时的断点续传。尽管目前没有浏览器实现 HTTP 断点续传,但一些下载软件支持它。而且,将来一些或所有 Web 浏览器都很有可能支持它。
此功能也有其局限性
- 在下载完成之前,文件数据会写入一个带有虚假名称的临时文件。下载完成后,浏览器会重命名文件。因此,在下载完成之前,文件无法被其他程序读取。
启用浏览器下载最简单的方法是将文件直接作为 URL 暴露给客户端,例如“http://mysite.com/GDrive/Data/Org2_53/Loc2_230/Site2_232/Folder2_242/My_244.data”,该 URL 映射到 InterACT 网站上文件的物理路径。无需额外编码工作。但是,这种方法有以下缺点
- 它向客户端暴露了太多信息。
- 在路径映射和 Web 场部署中复杂。
- 实现授权复杂。
- 对未来变化不灵活,例如文件夹结构变化。
一个更好的方法是编写一个 Web 服务或 Web API 或 HTTP 处理程序来处理来自 Web 浏览器的下载请求。然后我们可以提供像“http://mysite.com/api/files/download?id=244”这样的下载 URL,它更简洁、灵活、安全和可管理。
注意:不要使用 HttpResponse.WriteFile
,因为它无法将大文件传输到客户端。大小限制由服务器的硬件能力决定。Microsoft 提供了一个更好的解决方案:http://support.microsoft.com/kb/812406。
结论
总而言之,有一些重要的备忘录
- 对客户端文件系统的任何读写操作都需要客户端通过打开文件或保存文件对话框明确批准。
- 文件读取器 API 广泛支持使用。
- 文件写入器 API 的
FileSaver
可以由我们自己实现,并且广泛支持。 - 文件系统 API 和
FileWriter
仅在某些基于 WebKit 的浏览器(如 Chrome)中可用。它们只能在应用程序隔离的 Sandbox 中操作文件。 - 如果您不想使用任何插件技术,浏览器内置的下载功能是实现您特殊文件下载逻辑的最佳选择。
参考
[1] “W3C HTML5 File API”,http://www.w3.org/TR/FileAPI/
[2] “W3C HTML5 File API: Writer”,http://www.w3.org/TR/file-writer-api/
[3] “W3C HTML5 File API: Directories and System”,http://www.w3.org/TR/file-system-api/
[4] “The HTML5 Test”,http://html5test.com
[5] “Exploring the FileSystem APIs”,http://www.html5rocks.com/en/tutorials/file/filesystem/,Eric Bidelman