测试已测试 | ✗ |
语言语言 | Obj-CObjective C |
许可证 | Apache 2 |
发布最后发布 | 2016年11月 |
由 Holly Schinsky, Shazron Abdullah 维护。
标题:文件
Android | iOS | Windows 8.1 Store | Windows 8.1 Phone | Windows 10 Store | Travis CI |
---|---|---|---|---|---|
此插件实现了一个 File API,允许对设备上驻留的文件进行读写访问。
此插件基于几个规范,包括:HTML5 File API http://www.w3.org/TR/FileAPI/
目录和系统扩展的最新版本:http://www.w3.org/TR/2012/WD-file-system-api-20120417/ 尽管此插件的大部分代码是在较早的规范现行时编写的:http://www.w3.org/TR/2011/WD-file-system-api-20110419/
它还实现了 FileWriter 规范:http://dev.w3.org/2009/dap/file-system/file-writer.html
注意 虽然 W3C FileSystem 规范已弃用于浏览器,但该 FileSystem API 在本插件支持的平台上(支持平台列表中列出,浏览器平台除外)支持 Cordova 应用。
要了解如何使用该插件的一些建议,请查看页面底部的 示例。有关更多示例(以浏览器为中心),请参阅 HTML5 Rocks 的 FileSystem 文章。
有关其他存储选项的概述,请参阅 Cordova 的 存储指南。
此插件定义了全局的 cordova.file
对象。
尽管在全局范围内,但在 deviceready
事件之后才能使用。
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(cordova.file);
}
在 Apache Cordova 问题跟踪器 上报告问题
cordova plugin add cordova-plugin-file
* 这些平台不支持 FileReader.readAsArrayBuffer
也 FileWriter.write(blob)
.
截至v1.2.0版本,提供了重要文件系统目录的URL。每个URL的格式为file:///path/to/spot/,可以使用window.resolveLocalFileSystemURL()
将其转换为DirectoryEntry
。
cordova.file.applicationDirectory
- 应用程序安装的只读目录。(iOS、Android、BlackBerry 10、OSX、windows)
cordova.file.applicationStorageDirectory
- 应用程序沙箱的根目录;在iOS和windows上,此位置为只读(但某些子目录,如iOS上的/Documents
或在windows上的/localState
,是读写)。沙箱内的所有数据都仅对应用程序私有。(iOS、Android、BlackBerry 10、OSX)
cordova.file.dataDirectory
- 应用程序沙箱内部使用内部内存的持久私有数据存储(在Android上,如果您需要使用外部内存,请使用.externalDataDirectory
)。在iOS上,此目录不与iCloud同步(请使用.syncedDataDirectory
)。(iOS、Android、BlackBerry 10、windows)
cordova.file.cacheDirectory
- 用于缓存的本地数据文件或任何您可以轻松重新创建的文件的目录。当设备存储空间不足时,操作系统可能会删除这些文件,但应用程序不应依赖操作系统删除这些文件。(iOS、Android、BlackBerry 10、OSX、windows)
cordova.file.externalApplicationStorageDirectory
- 外部存储中的应用程序空间。(Android)
cordova.file.externalDataDirectory
- 外部存储中应用特定数据文件的位置。(Android)
cordova.file.externalCacheDirectory
- 外部存储中的应用程序缓存。(Android)
cordova.file.externalRootDirectory
- 外部存储(SD卡)的根目录。(Android、BlackBerry 10)
cordova.file.tempDirectory
- 操作系统可以随时清理的临时目录。请勿依赖操作系统清理此目录;您的应用程序应始终根据适用性删除文件。(iOS、OSX、windows)
cordova.file.syncedDataDirectory
- 包含应同步的应用特定文件(例如,到iCloud)。(iOS、windows)
cordova.file.documentsDirectory
- 仅对应用程序私有但对其他应用程序有意义的文件(例如,Office文件)。请注意,对于OSX,这是用户的~/Documents
目录。(iOS、OSX)
cordova.file.sharedDirectory
- 可供所有应用程序全局访问的文件。(BlackBerry 10)
虽然技术上是一个实现细节,但了解cordova.file.*
属性如何映射到真实设备上的物理路径非常有用。
设备路径 | cordova.file.* |
iosExtraFileSystems |
r/w? | persistent? | OS清除 | 同步 | 私有 |
---|---|---|---|---|---|---|---|
/var/mobile/Applications/<UUID>/ |
applicationStorageDirectory | - | r | N/A | N/A | N/A | Yes |
appname.app/
|
applicationDirectory | bundle | r | N/A | N/A | N/A | Yes |
www/
|
- | - | r | N/A | N/A | N/A | Yes |
Documents/
|
documentsDirectory | documents | r/w | Yes | No | Yes | Yes |
NoCloud/
|
- | documents-nosync | r/w | Yes | No | No | Yes |
Library
|
- | library | r/w | Yes | No | Yes? | Yes |
NoCloud/
|
dataDirectory | library-nosync | r/w | Yes | No | No | Yes |
Cloud/
|
syncedDataDirectory | - | r/w | Yes | No | Yes | Yes |
Caches/
|
cacheDirectory | cache | r/w | Yes* | Yes*** | No | Yes |
tmp/
|
tempDirectory | - | r/w | No** | Yes*** | No | Yes |
* 文件可以在应用程序重启和升级之间持续存在,但此目录可以在操作系统想要的时候清除。您的应用程序应能够重新创建任何可能被删除的内容。
** 文件可能在应用程序重启之间持续存在,但请不要依赖此行为。文件在更新之间不一定保证持续存在。当它适用时,您的应用程序应从此目录中删除文件,因为操作系统不保证何时(甚至是否)删除这些文件。
***操作系统可能随时清除此目录的内容,但请不要依赖这一行为。您应该根据您的应用程序需求适当清除此目录。
设备路径 | cordova.file.* |
AndroidExtraFileSystems |
r/w? | persistent? | OS清除 | 私有 |
---|---|---|---|---|---|---|
file:///android_asset/ |
applicationDirectory | assets | r | N/A | N/A | Yes |
/data/data/<app-id>/ |
applicationStorageDirectory | - | r/w | N/A | N/A | Yes |
cache
|
cacheDirectory | cache | r/w | Yes | Yes* | Yes |
files
|
dataDirectory | files | r/w | Yes | No | Yes |
Documents
|
documents | r/w | Yes | No | Yes | |
<sdcard>/ |
externalRootDirectory | sdcard | r/w | Yes | No | No |
Android/data/<app-id>/
|
externalApplicationStorageDirectory | - | r/w | Yes | No | No |
cache
|
externalCacheDirectry | cache-external | r/w | Yes | No** | No |
files
|
externalDataDirectory | files-external | r/w | Yes | No | No |
**操作系统可能会定期清除此目录,但请不要依赖这一行为。请根据您的应用程序适当的清除此目录内容。如果用户手动清除缓存,则此目录的内容将被删除。
***操作系统不会自动清除此目录;您需要自己管理内容。如果用户手动清除缓存,则目录内容将被移除。
注意:如果外部存储不可挂载,则 cordova.file.external*
属性将为 null
。
设备路径 | cordova.file.* |
r/w? | persistent? | OS清除 | 私有 |
---|---|---|---|---|---|
file:///accounts/1000/appdata/<app id>/ |
applicationStorageDirectory | r | N/A | N/A | Yes |
app/native
|
applicationDirectory | r | N/A | N/A | Yes |
data/webviews/webfs/temporary/local__0
|
cacheDirectory | r/w | No | Yes | Yes |
data/webviews/webfs/persistent/local__0
|
dataDirectory | r/w | Yes | No | Yes |
file:///accounts/1000/removable/sdcard |
externalRemovableDirectory | r/w | Yes | No | No |
file:///accounts/1000/shared |
sharedDirectory | r/w | Yes | No | No |
注意:当应用程序部署到工作范围时,所有路径相对于 /accounts/1000-enterprise。
设备路径 | cordova.file.* |
iosExtraFileSystems |
r/w? | OS清除 | 私有 |
---|---|---|---|---|---|
/Applications/<appname>.app/ |
- | bundle | r | N/A | Yes |
Content/Resources/
|
applicationDirectory | - | r | N/A | Yes |
~/Library/Application Support/<bundle-id>/ |
applicationStorageDirectory | - | r/w | No | Yes |
files/
|
dataDirectory | - | r/w | No | Yes |
~/Documents/ |
documentsDirectory | documents | r/w | No | No |
~/Library/Caches/<bundle-id>/ |
cacheDirectory | cache | r/w | No | Yes |
/tmp/ |
tempDirectory | - | r/w | Yes* | Yes |
/ |
rootDirectory | root | r/w | No** | No |
注意:这是非沙盒应用程序的布局。如果您启用沙盒,则 applicationStorageDirectory
将位于 ~/Library/Containers/<bundle-id>/Data/Library/Application Support
之下。
**文件将跨应用程序的重启和升级持续存在,但操作系统可以在任何时候清除此目录。您的应用程序应该能够重新创建可能被删除的任何内容。您应该根据您的应用程序需求适当的清除此目录。
**允许访问整个文件系统。这仅适用于非沙盒应用程序。
设备路径 | cordova.file.* |
r/w? | persistent? | OS清除 | 私有 |
---|---|---|---|---|---|
ms-appdata:/// |
applicationDirectory | r | N/A | N/A | Yes |
local/
|
dataDirectory | r/w | Yes | No | Yes |
temp/
|
cacheDirectory | r/w | No | Yes* | Yes |
temp/
|
tempDirectory | r/w | No | Yes* | Yes |
roaming/
|
syncedDataDirectory | r/w | Yes | No | Yes |
**操作系统可能会定期清除此目录。
在 Android 设备上存储持久文件的多个有效位置。有关各种可能性的详细讨论,请参阅此页面。
插件先前的版本会在启动时根据设备是否声明 SD 卡(或等效存储分区)已挂载来选择临时和持久文件的位置。如果 SD 卡已挂载,或者有一个大的内部存储分区可用(例如 Nexus 设备上),则持久文件将存储在该空间的根目录下。这意味着所有 Cordova 应用都可以看到该卡上的所有文件。
如果SD卡不可用,则旧版本会在 /data/data/<packageId>
下存储数据,这样可以使应用程序相互隔离,但仍可能导致数据之间共享。
现在可以在您的应用程序的 config.xml
文件中选择是否要在内部文件存储位置存储文件,或者使用旧的逻辑。为此,请将以下其中一行添加到 config.xml
。
<preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
如果没有这行代码,File插件将使用 Internal
作为默认设置。如果存在偏好标签,并且不是这些值之一,则应用程序将无法启动。
如果您的应用程序之前已经发行给用户,并使用此插件的旧版本(3.0.0之前),并在持久文件系统中存储了文件,那么如果您在 config.xml 中没有指定持久文件系统的位置,则应将首选项设置为 Compatibility
。将位置切换到“内部”意味着升级应用程序的现有用户可能会无法访问他们之前存储的文件,这取决于他们的设备。
如果您的应用程序是新的,或者从未在持久文件系统中存储文件,那么通常建议使用 Internal
设置。
在Android上,列出资源目录非常慢。您可以通过将 src/android/build-extras.gradle
添加到 Android 项目的根目录中(也要求Android版本 4.4 或更高)来加速这个过程。
Marshmallow 要求应用程序在读取/写入外部位置时请求权限。默认情况下,您的应用程序有权限写入 cordova.file.applicationStorageDirectory
和 cordova.file.externalApplicationStorageDirectory
,并且插件不会请求这两个目录的权限,除非外部存储未挂载。但是,由于一个限制,当外部存储未挂载时,它将请求写入 cordova.file.externalApplicationStorageDirectory
的权限。
cordova.file.applicationStorageDirectory
是只读的;试图在根目录中存储文件将失败。请使用为iOS定义的其他 cordova.file.*
属性之一(只有 applicationDirectory
和 applicationStorageDirectory
是只读的)。FileReader.readAsText(blob, encoding)
encoding
参数,总是使用 UTF-8 编码。在iOS设备上存储持久文件的有效位置有两个:Documents 文件夹和Library 文件夹。此插件的前几版始终在Documents 文件夹中存储持久文件,这让所有应用程序文件都可通过iTunes访问,这通常是意外的,尤其是对于处理大量小文件而不是生成完整文档以导出的应用程序,而这是目录的预期用途。
现在可以在您的应用程序的 config.xml
文件中设置首选项,以便选择是否将文件存储在文档目录或库目录中。为此,请将以下其中一行添加到 config.xml
。
<preference name="iosPersistentFileLocation" value="Library" />
<preference name="iosPersistentFileLocation" value="Compatibility" />
如果没有这行代码,File插件将使用 Compatibility
作为默认设置。如果存在偏好标签,并且不是这些值之一,则应用程序将无法启动。
如果您的应用程序之前已向用户发布,并使用本插件的旧版本(1.0之前)进行了发布,并且在持久文件系统中存储了文件,那么您应该将首选项设置为兼容性
。将位置切换到库
将意味着升级应用程序的现有用户将无法访问其之前存储的文件。
如果您的应用程序是新的,或者以前从未在持久文件系统中存储文件,那么通常建议使用库
设置。
Firefox OS 不原生支持文件系统API,而是作为indexedDB之上的适配层实现的。
copyTo
和moveTo
不支持目录以下数据路径得到支持
applicationDirectory
- 使用xhr
获取与应用程序打包的本地文件。dataDirectory
- 用于持久应用程序特定数据文件。cacheDirectory
- 应该在应用程序重启后继续存在的缓存文件(应用程序不应依赖于操作系统在此处删除文件)。fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)
时dir1不存在,该调用将失败。cdvfile://127.0.0.1
(本地资源)。也就是说,不能通过cdvfile
访问外部资源。close
函数不受支持。FileSaver
和BlobBuilder
不受此插件支持,也没有提供占位程序。requestAllFileSystems
。这个函数也在规范中缺失。create: true
标志为现有目录创建条目,目录条目不会被删除。readAsDataURL
函数,但是Chrome中的媒体类型取决于条目名的扩展名,IE中的媒体类型始终为空(根据规范,与text-plain
相同),Firefox中的媒体类型始终为application/octet-stream
。例如,如果内容是abcdefg
,那么Firefox返回data:application/octet-stream;base64,YWJjZGVmZw==
,IE返回data:;base64,YWJjZGVmZw==
,Chrome返回data:;;base64,YWJjZGVmZw==
。toInternalURL
返回的路径形式为file:///persistent/path/to/entry
(Firefox,IE)。Chrome返回的路径形式为cdvfile://127.0.0.1/persistent/file
。filePluginIsReady
事件。示例:window.addEventListener('filePluginIsReady', function(){ console.log('File plugin is ready');}, false);
您可以使用window.isFilePluginReadyRaised
函数检查事件是否已经触发。
window.initPersistentFileSystem
方法。默认的持久存储配额为5MB。--allow-file-access-from-files
运行参数来支持file:///
协议下的API。{create:true}
获取现有Entry
时,不修改File
对象。cancelable
属性设置为true,这与规范相反。toURL
函数根据应用程序的主机返回以filesystem:
开头的路径。例如,filesystem:file:///persistent/somefile.txt
,filesystem:https://127.0.0.1:8080/persistent/somefile.txt
。toURL
的结果不包含尾部斜杠。尽管如此,Chrome可以正确地解析带有尾部斜杠的URL。resolveLocalFileSystemURL
方法要求传入的url
具有filesystem
前缀。例如,resolveLocalFileSystemURL
的url
参数应采用格式filesystem:file:///persistent/somefile.txt
,而不是Android中的格式file:///persistent/somefile.txt
。toNativeURL
函数不受支持且没有占位符。setMetadata
函数在规范中没有说明,也不受支持。.
和..
不受支持。file:///
模式;仅支持托管模式(例如,https://127.0.0.1:xxxx)。requestFileSystem
函数的size
参数不会影响Firefox和IE中的文件系统。readAsBinaryString
函数在规范中没有说明,在IE中不受支持且没有占位符。file.type
始终为null。setMetadata
函数在规范中没有说明,但只支持modificationTime
字段的变化。copyTo
和moveTo
函数不支持目录。abort
和truncate
函数。writer.onprogress = function() { /*commands*/ };
在此插件v1.0.0中,FileEntry
和DirectoryEntry
结构已经改变,以更符合发布的规范。
该插件之前的(1.0.0之前的)版本在Entry对象的fullPath
属性中存储了设备绝对文件位置。这些路径通常看起来像
/var/mobile/Applications/<application UUID>/Documents/path/to/file (iOS)
/storage/emulated/0/path/to/file (Android)
这些路径也由Entry对象的toURL()
方法返回。
在v1.0.0版中,fullPath
属性是文件的路径,相对于HTML文件系统的根目录。因此,上述路径现在都将由带有fullPath
的FileEntry
对象表示
/path/to/file
如果您的应用程序使用设备绝对路径,并且您之前通过Entry
对象的fullPath
属性检索了这些路径,那么您应该更新代码以使用entry.toURL()
。
为了向后兼容,resolveLocalFileSystemURL()
方法将接受一个设备绝对路径,并且只要该文件存在于TEMPORARY
或PERSISTENT
文件系统中,它将返回相对应的Entry
对象。
这尤其是一个问题,File-Transfer插件之前使用设备绝对路径(并且仍然可以接受它们),现在已更新为正确处理FileSystem URL,所以将entry.fullPath
替换为entry.toURL()
应该解决该插件与设备上的文件一起使用时出现的问题。
在v1.1.0中,toURL()
的返回值已更改(见CB-6394),尽可能返回一个绝对'file://' URL。为了确保一个'cdvfile:'-URL,现在可以使用toInternalURL()
。此方法现在将返回以下形式的文件系统URL
cdvfile://127.0.0.1/persistent/path/to/file
这可以用来唯一地识别文件。
目的
cdvfile://127.0.0.1/persistent|temporary|another-fs-root*/path/to/file
可以用作平台无关的文件路径。cdvfile路径由核心插件支持 - 例如,您可以通过cordova-plugin-file-transfer
将mp3文件下载到cdvfile路径并使用cordova-plugin-media
播放它。
注意:有关可用的fs根的更多详细信息,请参阅文件存储位置、文件系统结构和配置插件(可选)。
要将cdvfile
用作标签的src
属性,您可以将它通过获取的fileEntry的toURL()
方法转换为本地路径,您可以通过resolveLocalFileSystemURL
获取该路径 - 下面有一些示例。
您还可以在DOM中直接使用cdvfile://
路径,例如
<img src="cdvfile://127.0.0.1/persistent/img/logo.png" />
注意:此方法需要更新以下内容安全规则
cdvfile:
方案添加到索引页面的Content-Security-Policy
元标签中,例如<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:
cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
<access origin="cdvfile://*" />
添加到config.xml
。将cdvfile://转换为本地路径
resolveLocalFileSystemURL('cdvfile://127.0.0.1/temporary/path/to/file.mp4', function(entry) {
var nativePath = entry.toURL();
console.log('Native URI: ' + nativePath);
document.getElementById('video').src = nativePath;
将本地路径转换为cdvfile://
resolveLocalFileSystemURL(nativePath, function(entry) {
console.log('cdvfile URI: ' + entry.toInternalURL());
在核心插件中使用cdvfile
fileTransfer.download(uri, 'cdvfile://127.0.0.1/temporary/path/to/file.mp3', function (entry) { ...
var my_media = new Media('cdvfile://127.0.0.1/temporary/path/to/file.mp3', ...);
my_media.play();
cdvfile://
路径(路径可以转换为本地路径)。当抛出错误时,以下代码之一将用于。
代码 | 常量 |
---|---|
1 | NOT_FOUND_ERR |
2 | SECURITY_ERR |
3 | ABORT_ERR |
4 | NOT_READABLE_ERR |
5 | ENCODING_ERR |
6 | NO_MODIFICATION_ALLOWED_ERR |
7 | INVALID_STATE_ERR |
8 | SYNTAX_ERR |
9 | INVALID_MODIFICATION_ERR |
10 | QUOTA_EXCEEDED_ERR |
11 | TYPE_MISMATCH_ERR |
12 | PATH_EXISTS_ERR |
可以按平台配置可用的文件系统集合。iOS和Android都识别config.xml
中的一个标签,该标签命名要安装的文件系统。默认情况下,所有文件系统根目录均启用。
<preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />
files
:应用程序的内部文件存储目录files-external
:应用程序的外部文件存储目录sdcard
:全局外部文件存储目录(这是SD卡的根目录,如果已安装)。您必须具有android.permission.WRITE_EXTERNAL_STORAGE
权限才能使用此目录。cache
:应用程序的内部缓存目录cache-external
:应用程序的外部缓存目录assets
:应用程序的 bundles(只读)root
:整个设备的文件系统Android还支持一个名为“documents”的特殊文件系统,它代表“files”文件系统中“/Documents/”子目录。
library
:应用程序的 Library 目录documents
:应用程序的 Documents 目录cache
:应用程序的 Cache 目录bundle
:应用程序的 bundle;应用程序在磁盘上的位置(只读)root
:整个设备的文件系统默认情况下,library 和 documents 目录可以同步到iCloud。您还可以请求另外两个文件系统,即library-nosync
和documents-nosync
,这两个文件系统代表一个特殊的非同步目录,位于/Library
或/Documents
文件系统中。
文件插件允许您在应用程序中执行诸如将文件存储在临时或持久存储位置(沙箱存储)以及存储在平台相关位置的操作。本节中的代码示例演示了不同的任务,包括
在您使用文件插件 API 之前,您可以使用 requestFileSystem
来获取对文件系统的访问权限。当这样做时,您可以请求持久或临时存储。持久存储除非用户授权,否则不会被删除。
当您使用 requestFileSystem
获取文件系统访问权限时,只授予对沙箱文件系统的访问权限(沙箱限制对应用程序自身的访问),而不是对设备的任何文件系统位置的通用访问。(要访问沙箱存储之外的其他文件系统位置,请使用其他方法,例如window.requestLocalFileSystemURL,它支持平台特定的位置。例如,请参阅“附加文件”)
以下是频繁使用持久存储的一个示例。
注意 当针对WebView客户端(而不是浏览器)或原生应用(Windows)时,在持久存储之前无需使用
requestQuota
。
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {
console.log("fileEntry is file?" + fileEntry.isFile.toString());
// fileEntry.name == 'someFile.txt'
// fileEntry.fullPath == '/someFile.txt'
writeFile(fileEntry, null);
}, onErrorCreateFile);
}, onErrorLoadFs);
成功回调接收 FileSystem 对象(fs)。使用 fs.root
来返回一个 DirectoryEntry 对象,您可以使用它来创建或获取一个文件(通过调用 getFile
)。在这个示例中,fs.root
是一个 DirectoryEntry 对象,代表沙箱文件系统中的持久存储。
getFile
的成功回调接收一个 FileEntry 对象。您可以使用它来执行文件读写操作。
以下是请求临时存储的一个示例。如果设备内存不足,操作系统可能会删除临时存储。
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
console.log('file system open: ' + fs.name);
createFile(fs.root, "newTempFile.txt", false);
}, onErrorLoadFs);
当使用临时存储时,你可以通过调用 getFile
来创建或获取文件。正如持久化存储示例所示,这将为您提供一个 FileEntry 对象,您可以使用此对象进行读取或写入操作。
function createFile(dirEntry, fileName, isAppend) {
// Creates a new file or returns the file if it already exists.
dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
writeFile(fileEntry, null, isAppend);
}, onErrorCreateFile);
}
一旦拥有 FileEntry 对象,您可以通过调用 createWriter
来向文件写入,这在成功回调中返回 FileWriter 对象。调用 FileWriter 的 write
方法来写入文件。
function writeFile(fileEntry, dataObj) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file write...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file write: " + e.toString());
};
// If data object is not passed in,
// create a new Blob instead.
if (!dataObj) {
dataObj = new Blob(['some file data'], { type: 'text/plain' });
}
fileWriter.write(dataObj);
});
}
您还需要 FileEntry 对象来读取现有的文件。使用 FileEntry 的文件属性来获取文件引用,然后创建一个新的 FileReader 对象。您可以使用类似于 readAsText
的方法来开始读取操作。当读取操作完成时,this.result
存储读取操作的结果。
function readFile(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
console.log("Successful file read: " + this.result);
displayFileData(fileEntry.fullPath + ": " + this.result);
};
reader.readAsText(file);
}, onErrorReadFile);
}
当然,您通常希望追加现有文件而不是创建新文件。这里有一个例子。此示例显示您可以使用 window.resolveLocalFileSystemURL
访问文件系统的一种另一种方式。在此示例中,将跨平台 Cordova 文件 URL, cordova.file.dataDirectory,传递给函数。成功回调接收一个 DirectoryEntry 对象,您可以使用它来创建文件等操作。
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
console.log('file system open: ' + dirEntry.name);
var isAppend = true;
createFile(dirEntry, "fileToAppend.txt", isAppend);
}, onErrorLoadFs);
除了此用法外,您还可以使用 resolveLocalFileSystemURL
来获取访问不属于沙盒存储系统的一些文件系统位置。有关更多信息,请参阅 文件存储位置;许多这些存储位置是特定于平台的。您也可以使用 cdvfile 协议 将跨平台文件系统位置传递给 resolveLocalFileSystemURL
。
对于追加操作,前述代码中调用的 createFile
函数(请参阅前述示例中的实际代码)中没有新增的内容。createFile
调用 writeFile
。在 writeFile
中,您检查是否请求了追加操作。
一旦您有了 FileWriter 对象,调用 seek
方法,并传递您想要写入的位置的索引值。在此示例中,您还测试文件是否存在。调用 seek 后,然后调用 FileWriter 的写入方法。
function writeFile(fileEntry, dataObj, isAppend) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file read...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file read: " + e.toString());
};
// If we are appending data to file, go to the end of the file.
if (isAppend) {
try {
fileWriter.seek(fileWriter.length);
}
catch (e) {
console.log("file doesn't exist!");
}
}
fileWriter.write(dataObj);
});
}
我们已显示了如何写入沙盒文件系统中刚创建的文件。如果您需要获取对现有文件的访问权限并将其转换为可在设备上存储的内容怎么办?在此示例中,您使用 xhr 请求获取文件,然后将其保存到沙盒文件系统的缓存中。
在获取文件之前,使用 requestFileSystem
获取 FileSystem 引用。通过在方法调用中传递 window.TEMPORARY(与之前相同),返回的 FileSystem 对象(fs)代表沙盒文件系统的缓存。使用 fs.root
获取所需的 DirectoryEntry 对象。
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
console.log('file system open: ' + fs.name);
getSampleFile(fs.root);
}, onErrorLoadFs);
为了完整性,这里提供了获取 Blob 图像的 xhr 请求。此代码中没有 Cordova 特定内容,除了您将已获得的 DirectoryEntry 引用作为参数传递给 saveFile 函数。您将保存 blob 图像,在读取文件后(以验证操作)稍后显示此文件。
function getSampleFile(dirEntry) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cordova.net.cn/static/img/cordova_bot.png', true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (this.status == 200) {
var blob = new Blob([this.response], { type: 'image/png' });
saveFile(dirEntry, blob, "downloadedImage.png");
}
};
xhr.send();
}
注意针对Cordova 5安全,前面的代码要求您将域名 https://cordova.net.cn 添加到index.html中的Content-Security-Policy元素。
获取文件后,将内容复制到一个新文件中。当前的DirectoryEntry对象已与app缓存关联。
function saveFile(dirEntry, fileData, fileName) {
dirEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
writeFile(fileEntry, fileData);
}, onErrorCreateFile);
}
在writeFile中,您将Blob对象传递给dataObj,并将它保存到新文件中。
function writeFile(fileEntry, dataObj, isAppend) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file write...");
if (dataObj.type == "image/png") {
readBinaryFile(fileEntry);
}
else {
readFile(fileEntry);
}
};
fileWriter.onerror = function(e) {
console.log("Failed file write: " + e.toString());
};
fileWriter.write(dataObj);
});
}
将内容写入文件后,读取并显示它。您已将图片保存为二进制数据,因此可以使用FileReader.readAsArrayBuffer读取它。
function readBinaryFile(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
console.log("Successful file write: " + this.result);
displayFileData(fileEntry.fullPath + ": " + this.result);
var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
displayImage(blob);
};
reader.readAsArrayBuffer(file);
}, onErrorReadFile);
}
读取数据后,可以使用如下代码显示图片。使用window.URL.createObjectURL获取Blob图片的DOM字符串。
function displayImage(blob) {
// Displays image if result is a valid DOM string for an image.
var elem = document.getElementById('imageFile');
// Note: Use window.URL.revokeObjectURL when finished with image.
elem.src = window.URL.createObjectURL(blob);
}
要使用FileEntry显示图片,您可以调用toURL
方法。
function displayImageByFileURL(fileEntry) {
var elem = document.getElementById('imageFile');
elem.src = fileEntry.toURL();
}
如果您使用特定平台的URI而不是FileEntry来显示图片,您可能需要在index.html中的Content-Security-Policy元素中包含URI的主要部分。例如,在Windows 10上,您可以包括ms-appdata:
。以下是示例。
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
在此代码中,您在应用存储位置的根目录中创建目录。您可以用任何可写存储位置(即任何DirectoryEntry)使用此代码。在这里,您通过将fs.root传递给此函数来写入应用缓存(假设您使用了window.TEMPORARY获取FileSystem对象)。
此代码在应用缓存中创建了/NewDirInRoot/images文件夹。对于特定平台的值,请查看文件系统布局。
function createDirectory(rootDirEntry) {
rootDirEntry.getDirectory('NewDirInRoot', { create: true }, function (dirEntry) {
dirEntry.getDirectory('images', { create: true }, function (subDirEntry) {
createFile(subDirEntry, "fileInNewSubDir.txt");
}, onErrorGetDir);
}, onErrorGetDir);
}
创建子文件夹时,需要像前面代码中所示单独创建每个文件夹。