对于文件操作来说是开发中的常用模块,这个问题一直困恼了很多天,正好项目有一个模块用到了文件的操作,需求是用(cordova-plugin-file
)插件(访问文件的路径),录制了一小段语音(cordova-plugin-media),需要先存储起来(有默认的存储地址),然后利用(cordova-plugin-file-transfer)插件的方法,把存储中的语音文件获取进行上传,然后进行回应,之后返回结果合成文字,然后再语音播放出来。就是小的智能问答系统。由于android平台下的文件目录系统下能够直接查看,但是在ios 中查看一个应用的目录没那个容易。
我首先尝试使用PP助手来查看但是提示的是要越狱,为了看到文件,直接把touch给越狱了,但是未果在应用列表,选择单个应用,查看文件,结果查看的还是应用外部的文件夹,不如DCIM,Books,AirFair,Airlock,PhotoData 等,根本不是我想要看到的结果,后来又忙活了半天,终于找到了一个正解。
如何查看真机的沙盒(图文教程) 虽然是博主转载的,还是要再次感谢!
下面我列出下插件包cordova-plugin-file里面关于ios 文件系统的支持情况,供大家在遇到的时候有一个参考,基于h5的cordova项目操作源生的文件。摘自README.md文件有如下内容。
## Where to Store Files
As of v1.2.0, URLs to important file-system directories are provided.
Each URL is in the form _file:///path/to/spot/_, and can be converted to a
`DirectoryEntry` using `window.resolveLocalFileSystemURL()`.
* `cordova.file.applicationDirectory` - Read-only directory where the application
is installed. (_iOS_, _Android_, _BlackBerry 10_, _OSX_, _windows_)
* `cordova.file.applicationStorageDirectory` - Root directory of the application's
sandbox; on iOS & windows this location is read-only (but specific subdirectories[like
`/Documents` on iOS or `/localState` on windows] are read-write). All data contained within
is private to the app. (_iOS_, _Android_, _BlackBerry 10_, _OSX_)
* `cordova.file.dataDirectory` - Persistent and private data storage within the
application's sandbox using internal memory (on Android, if you need to use
external memory, use `.externalDataDirectory`). On iOS, this directory is not
synced with iCloud (use `.syncedDataDirectory`). (_iOS_, _Android_, _BlackBerry 10_, _windows_)
* `cordova.file.cacheDirectory` - Directory for cached data files or any files
that your app can re-create easily. The OS may delete these files when the device
runs low on storage, nevertheless, apps should not rely on the OS to delete files
in here. (_iOS_, _Android_, _BlackBerry 10_, _OSX_, _windows_)
* `cordova.file.externalApplicationStorageDirectory` - Application space on
external storage. (_Android_)
* `cordova.file.externalDataDirectory` - Where to put app-specific data files on
external storage. (_Android_)
* `cordova.file.externalCacheDirectory` - Application cache on external storage.
(_Android_)
* `cordova.file.externalRootDirectory` - External storage (SD card) root. (_Android_, _BlackBerry 10_)
* `cordova.file.tempDirectory` - Temp directory that the OS can clear at will. Do not
rely on the OS to clear this directory; your app should always remove files as
applicable. (_iOS_, _OSX_, _windows_)
* `cordova.file.syncedDataDirectory` - Holds app-specific files that should be synced
(e.g. to iCloud). (_iOS_, _windows_)
* `cordova.file.documentsDirectory` - Files private to the app, but that are meaningful
to other application (e.g. Office files). Note that for _OSX_ this is the user's`~/Documents` directory. (_iOS_, _OSX_)
* `cordova.file.sharedDirectory` - Files globally available to all applications (_BlackBerry 10_)
### iOS File System Layout
| Device Path | `cordova.file.*` |`iosExtraFileSystems` | r/w? | persistent? | OS clears | sync | private |
|:-----------------------------------------------|:----------------------------|:----------------------|:----:|:-----------:|:---------:|:----:|:-------:|
| `/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 |
\* Files persist across app restarts and upgrades, but this directory can
be cleared whenever the OS desires. Your app should be able to recreate any
content that might be deleted.
\*\* Files may persist across app restarts, but do not rely on this behavior. Files
are not guaranteed to persist across updates. Your app should remove files from
this directory when it is applicable, as the OS does not guarantee when (or even
if) these files are removed.
\*\*\* The OS may clear the contents of this directory whenever it feels it is
necessary, but do not rely on this. You should clear this directory as
appropriate for your application.
基于此,大家可以对ios应用的文件目录有一个大致的了解。如果一点基础都没有,大家可以参考之前的文章 iOS学习之沙盒机制
总结:1.对于各个平台的差异性,在相对应的插件中有相关的说明,可以在README.md文件中进行查看,其中还有使用说明,类似于开发的API 这在开发中十分重要!
2.锻炼自己的搜索能力,关键字搜索技巧,要不然,手机越狱了也没有找到。呜呜····
3.对于一些底层的操作,感觉还是用原声的实现比较好,三方插件也可以实现,但是很繁琐(个人认为),目的是简化开发成本,提高效率的,结果走了绕圈的路,算是涨点经验吧。
4.不能完全相信操作使用手册,在实际中发现并非完全正确。或者是没有完完全全搞懂。
比如 摘自上文media的README.me文件:
### iOS Quirks
- __numberOfLoops__: Pass this option to the `play` method to specify
the number of times you want the media file to play, e.g.:
var myMedia = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3")
myMedia.play({ numberOfLoops: 2 })
- __playAudioWhenScreenIsLocked__: Pass in this option to the `play`
method to specify whether you want to allow playback when the screen
is locked. If set to `true` (the default value), the state of the
hardware mute button is ignored, e.g.:
var myMedia = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3")
myMedia.play({ playAudioWhenScreenIsLocked : false })
- __order of file search__: When only a file name or simple path is
provided, iOS searches in the `www` directory for the file, then in
the application's `documents/tmp` directory:
var myMedia = new Media("audio/beer.mp3")
myMedia.play() // first looks for file in www/audio/beer.mp3 then in <application>/documents/tmp/audio/beer.mp3
实际测试中发现是这样子的:
下面是我经过反复测试得到的结果:
var fileURL = cordova.file.cacheDirectory + recog_src; //音频地址 (可能的首选)
打印log 文件地址file:///var/mobile/Containers/Data/Application/CE28CF34-18B0-46D1-AB1E-31DC28227E3E/Library/Caches/qxj_Chat.wav
var fileURL = cordova.file.applicationStorageDirectory + recog_src; //音频地址 (不适用)
打印的log file:///var/mobile/Containers/Data/Application/F6B713A7-8951-490D-961F-2F5D245E9C3F/qxj_Chat.wav
var fileURL = cordova.file.dataDirectory + recog_src; //音频地址 (不适用)
打印的log 文件地址file:///var/mobile/Containers/Data/Application/963BEF7B-DA2C-4203-A01F-EA2D69185316/Library/NoCloud/qxj_Chat.wav
var fileURL = cordova.file.syncedDataDirectory + recog_src; //音频地址 (不适用)
打印log 文件地址file:///var/mobile/Containers/Data/Application/CD70862A-D0CB-4DB6-89BC-3FC447D30933/Library/Cloud/qxj_Chat.wav
var fileURL = cordova.file.documentsDirectory + recog_src; //音频地址 (不适用)
打印log upload error source file:///var/mobile/Containers/Data/Application/EB48A50D-1E5B-4B4D-8B32-BA054706EC2C/Documents/qxj_Chat.wav
而qxj_Chat.wav 就是我想看到的文件,但是路径和说明中的不一样,这也是程序一直报错(没有找到相关的目录和路径)的原因。
题外话:另外附一张源生的应用的沙箱目录,大家可以做一下对比。
小结:在Android平台下可以使用这个插件后去路径:
var fileURL = cordova.file.externalRootDirectory + recog_src; //音频地址 是在外存储的根目录下 recog_src=qxj_Chat.wav
在IOS平台下可以使用这个插件后去路径:
var fileURL = cordova.file.tempDirectory + recog_src;//音频地址 //tmp
文件名字获取如下js代码:
fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); //qxj_Chat.wav
如有不妥之处,欢迎批评指正,共同学习,共同进步!