• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 用户文件URI介绍
2<!--Kit: Core File Kit-->
3<!--Subsystem: FileManagement-->
4<!--Owner: @wang_zhangjun; @zhuangzhuang-->
5<!--Designer: @wang_zhangjun; @zhuangzhuang; @renguang1116-->
6<!--Tester: @liuhonggang123; @yue-ye2; @juxiaopang-->
7<!--Adviser: @foryourself-->
8
9用户文件URI是文件的唯一标识,在对用户文件进行访问与修改等操作时往往都会使用到URI,不建议开发者解析URI中的片段用于业务代码开发,不同类型的URI使用方式将在下文详细介绍。
10
11## URI的类型
12
13URI类型可以归纳为文档类URI和媒体文件URI两类
14
15- 文档类URI:由picker拉起文件管理器选择或保存返回,以及通过fileAccess模块获取。具体获取方式参见[文档类URI获取方式](#文档类uri获取方式)。
16- 媒体文件URI:由picker通过拉起图库选择图片或者视频返回,通过photoAccessHelper模块获取图片或者视频文件的URI,以及通过userFileManager模块获取图片、视频或者音频文件的URI。具体获取方式参见[媒体文件URI获取方式](#媒体文件uri获取方式)。
17
18![user-file-uri-intro](figures/user-file-uri-intro.png)
19
20## 文档类URI
21
22### 文档类URI介绍
23
24**文档类URI的格式类型为:**
25
26'file://docs/storage/Users/currentUser/\<relative_path\>/test.txt'
27
28**其中各个字段表示的含义为:**
29
30| URI字段          | 说明        |
31| ------------- | ------------------- |
32| 'file://docs/storage/Users/currentUser/' | 文件管理器的根目录。|
33| '\<relative_path\>/' | 文件在根目录下的相对路径。例如:'Download/'和'Documents/'。|
34| 'test.txt' | 用户文件系统中存储的文件名,支持的文件类型为文件管理器支持的所有类型,以文件管理器为准。例如txt、jpg、mp4和mp3等格式的文件。|
35
36### 文档类URI获取方式
37
381. 通过[DocumentViewPicker接口](../reference/apis-core-file-kit/js-apis-file-picker.md#documentviewpicker)选择或保存文件,返回选择或保存的文件URI。
39
402. 通过[AudioViewPicker接口](../reference/apis-core-file-kit/js-apis-file-picker.md#audioviewpicker)选择或保存文件,返回选择或保存的文件URI。<!--Del-->
41
423. 通过[fileAccess模块](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)获取文档类目录下的文件得到对应文件的[FileInfo](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#fileinfo)对象,此对象中就包含对应文件或者目录的URI属性,此模块中的接口为系统接口,使用此模块需要注意应用是否为系统应用。支持获取文件URI的目录有:
43   - 外部存储目录
44   - Docs目录
45   - Download目录
46   - Desktop目录
47   - Documents目录
48   - Share共享盘目录
49<!--DelEnd-->
50
51### 文档类URI的使用方式
52
53normal等级的应用使用此类URI的方式只能通过[fs模块](../reference/apis-core-file-kit/js-apis-file-fs.md)进行进一步处理,其他模块使用此URI时会报没有权限的错误。示例代码参见picker中的[选择文档类文件](./select-user-file.md#选择文档类文件)和[保存文档类文件](./save-user-file.md#保存文档类文件)。<!--Del-->
54
55system_basic等级及以上的应用使用此类URI的方式除了上述通过fs模块外还可以通过[fileAccess模块](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)进行进一步处理,使用此模块需要在配置文件module.json5中声明ohos.permission.FILE_ACCESS_MANAGERohos.permission.GET_BUNDLE_INFO_PRIVILEGED 权限,此权限为system_basic权限,仅供系统应用使用。其他模块使用此URI会报没有权限的错误。下面示例为使用fileAccess模块创建文件得到URI后对其进行重命名操作:
56
571. 通过[fileAccess模块](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md)获取文件URI。
582. 使用获取到的文件URI进行重命名操作。
59
60```ts
61import { BusinessError } from '@kit.BasicServicesKit';
62import { Want } from '@kit.AbilityKit';
63import { common } from '@kit.AbilityKit';
64import { fileAccess } from '@kit.CoreFileKit';
65// context 是EntryAbility 传过来的context,确保this.getUIContext().getHostContext()返回结果为UIAbilityContext
66let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
67
68async function example(context: common.UIAbilityContext) {
69    let fileAccessHelper: fileAccess.FileAccessHelper;
70    // wantInfos 从getFileAccessAbilityInfo()获取
71    let wantInfos: Array<Want> = [
72      {
73        bundleName: "com.ohos.UserFile.ExternalFileManager",
74        abilityName: "FileExtensionAbility",
75      },
76    ]
77    try {
78      fileAccessHelper = fileAccess.createFileAccessHelper(context, wantInfos);
79      if (!fileAccessHelper) {
80        console.error("createFileAccessHelper interface returns an undefined object");
81      }
82      // 以内置存储目录为例
83      // 示例代码sourceUri表示Download目录,该URI是对应的fileInfo中URI
84      // 开发者应根据自己实际获取的URI进行开发
85      let sourceUri: string = "file://docs/storage/Users/currentUser/Download";
86      let displayName: string = "file1.txt";
87      let fileUri: string;
88      try {
89        // 创建文件返回该文件的URI
90        fileUri = await fileAccessHelper.createFile(sourceUri, displayName);
91        if (!fileUri) {
92          console.error("createFile return undefined object");
93        }
94        console.info("createFile success, fileUri: " + JSON.stringify(fileUri));
95        // 将刚创建的文件进行重命名,返回新文件的URI
96        let renameUri = await fileAccessHelper.rename(fileUri, "renameFile.txt");
97        console.info("rename success, renameUri: " + JSON.stringify(renameUri));
98      } catch (err) {
99        let error: BusinessError = err as BusinessError;
100        console.error("createFile failed, errCode:" + error.code + ", errMessage:" + error.message);
101      }
102    } catch (err) {
103      let error: BusinessError = err as BusinessError;
104      console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
105    }
106  }
107```
108<!--DelEnd-->
109
110## 媒体文件URI
111
112### 媒体文件URI介绍
113
114**媒体文件URI的格式类型为:**
115
116图片URI格式:
117
118- 'file://media/Photo/\<id\>/IMG_datetime_0001/displayName.jpg'
119
120视频URI格式:
121
122- 'file://media/Photo/\<id>/VID_datetime_0001/displayName.mp4'
123
124音频URI格式:
125
126- 'file://media/Audio/\<id>/AUD_datetime_0001/displayName.mp3'
127
128**其中各个字段表示的含义为:**
129
130| URI字段          | 说明        |
131| ------------- | ------------------- |
132| 'file://media' | 表示这个URI是媒体文件。 |
133| 'Photo' | 表示这个URI是媒体文件中的图片或者视频类文件。 |
134| 'Audio' | 表示这个URI是媒体文件中的音频类文件。 |
135| '\<id>' | 表示在数据库中多个表中处理后的值,并不是指表中的file_id列,注意请不要使用此id去数据库中查询具体文件。 |
136| 'IMG_datetime_0001' | 表示图片文件在用户文件系统中存储的文件名去掉后缀剩下的部分。 |
137| 'VID_datetime_0001' | 表示视频文件在用户文件系统中存储的文件名去掉后缀剩下的部分。 |
138| 'AUD_datetime_0001' | 表示音频文件在用户文件系统中存储的文件名去掉后缀剩下的部分。 |
139|<!--DelRow--> 'displayName.jpg' | 表示图片文件对外展示的displayName,使用[userFileManager.commitModify](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#commitmodify)接口重命名修改的就是这个值,需要注意这个值修改后URI也会发生改变。 |
140|<!--DelRow--> 'displayName.mp4' | 表示视频文件对外展示的displayName,使用[userFileManager.commitModify](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#commitmodify)接口重命名修改的就是这个值,需要注意这个值修改后URI也会发生改变。 |
141|<!--DelRow--> 'displayName.mp3' | 表示音频文件对外展示的displayName,使用[userFileManager.commitModify](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#commitmodify)接口重命名修改的就是这个值,需要注意这个值修改后URI也会发生改变。 |
142
143### 媒体文件URI获取方式
144
1451. 通过[PhotoAccessHelper的PhotoViewPicker](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoViewPicker.md)选择媒体文件,返回选择的媒体文件文件的URI。
146
1472. 通过[photoAccessHelper模块](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper.md)中的[getAssets](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAccessHelper.md#getassets)或[createAsset](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAccessHelper.md#createasset)接口获取媒体文件对应文件的URI。<!--Del-->
148
1493. 通过[userFileManager模块](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md)中的[getPhotoAssets](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#getphotoassets)、[getAudioAssets](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#getaudioassets)、[createAudioAsset](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#createaudioasset10)或[createPhotoAsset](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md#createphotoasset)接口获取媒体文件对应文件的URI。
150<!--DelEnd-->
151
152### 媒体文件URI的使用方式
153
154normal等级的应用使用此类URI可以通过[photoAccessHelper模块](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper.md)进行进一步处理。示例代码参见媒体资源使用指导中的[指定URI获取图片或视频资源](../media/medialibrary/photoAccessHelper-photoviewpicker.md#指定uri获取图片或视频资源)。此接口需要申请相册管理模块读权限([ohos.permission.READ_IMAGEVIDEO](../media/medialibrary/photoAccessHelper-overview.md#能力范围)),在使用中需要注意应用是否有此权限。<!--Del-->
155
156system_basic等级及以上的应用使用此类URI的方式除了上述通过photoAccessHelper模块外还可以通过[userFileManager模块](../reference/apis-core-file-kit/js-apis-userFileManager-sys.md)进行进一步处理,接口详细使用方式见接口文档。
157<!--DelEnd-->
158
159若normal等级的应用不想申请权限也可以通过临时授权的方式使用[PhotoAccessHelper的PhotoViewPicker](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoViewPicker.md)得到的URI使用[photoAccessHelper.getAssets接口](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAccessHelper.md#getassets)获取对应URI的PhotoAsset对象。通过此方式获取的PhotoAsset对象可调用[getThumbnail](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAsset.md#getthumbnail)方法获取缩略图,并通过[get接口](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAsset.md#get)方法读取[PhotoKeys](../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-e.md#photokeys)中的部分信息。
160
161以下为PhotoKeys中支持临时授权方式可以读取的信息:
162
163| 名称          | 值              | 说明                                                       |
164| ------------- | ------------------- | ---------------------------------------------------------- |
165| URI           | 'uri'                 | 文件URI。                                                   |
166| PHOTO_TYPE    | 'media_type'           | 媒体文件类型。                                              |
167| DISPLAY_NAME  | 'display_name'        | 显示名字。                                                   |
168| SIZE          | 'size'                | 文件大小。                                                   |
169| DATE_ADDED    | 'date_added'          | 文件创建时的Unix时间戳(单位:秒)。            |
170| DATE_MODIFIED | 'date_modified'       | 文件修改时的Unix时间戳(单位:秒)。修改文件名不会改变此值,当文件内容发生修改时才会更新。 |
171| DURATION      | 'duration'            | 持续时间(单位:毫秒)。                                    |
172| WIDTH         | 'width'               | 图片宽度(单位:像素)。                                    |
173| HEIGHT        | 'height'              | 图片高度(单位:像素)。                                      |
174| DATE_TAKEN    | 'date_taken'          | 拍摄时的Unix时间戳(单位:秒)。                |
175| ORIENTATION   | 'orientation'         | 图片文件的方向。                                             |
176| TITLE         | 'title'               | 文件标题。                                                   |
177
178下面为通过临时授权方式使用媒体文件URI进行获取缩略图和读取文件部分信息的示例代码:
179
180```ts
181import { photoAccessHelper } from '@kit.MediaLibraryKit';
182import { BusinessError } from '@kit.BasicServicesKit';
183import { dataSharePredicates } from '@kit.ArkData';
184import { common } from '@kit.AbilityKit';
185
186// 定义一个URI数组,用于接收PhotoViewPicker选择图片返回的URI
187let uris: Array<string> = [];
188// context 是EntryAbility 传过来的context,确保this.getUIContext().getHostContext()返回结果为UIAbilityContext
189let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
190
191// 调用PhotoViewPicker.select选择图片
192async function photoPickerGetUri(context: common.UIAbilityContext) {
193  try {
194    let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
195    PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
196    PhotoSelectOptions.maxSelectNumber = 1;
197    let photoPicker = new photoAccessHelper.PhotoViewPicker();
198    photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {
199      console.info('PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));
200      uris = PhotoSelectResult.photoUris;
201    }).catch((err: BusinessError) => {
202      console.error(`PhotoViewPicker.select failed with err, code is ${err.code}, message is ${err.message}`);
203    });
204  } catch (error) {
205    let err: BusinessError = error as BusinessError;
206    console.error(`PhotoViewPicker failed with err, code is ${err.code}, message is ${err.message}`);
207  }
208}
209
210async function uriGetAssets() {
211try {
212    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
213    let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();
214    // 配置查询条件,使用PhotoViewPicker选择图片返回的uri进行查询
215    predicates.equalTo('uri', uris[0]);
216    let fetchOption: photoAccessHelper.FetchOptions = {
217      fetchColumns: [photoAccessHelper.PhotoKeys.WIDTH, photoAccessHelper.PhotoKeys.HEIGHT, photoAccessHelper.PhotoKeys.TITLE, photoAccessHelper.PhotoKeys.DURATION],
218      predicates: predicates
219    };
220    let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOption);
221    // 得到URI对应的PhotoAsset对象,读取文件的部分信息
222    const asset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
223    console.info('asset displayName: ', asset.displayName);
224    console.info('asset uri: ', asset.uri);
225    console.info('asset photoType: ', asset.photoType);
226    console.info('asset width: ', asset.get(photoAccessHelper.PhotoKeys.WIDTH));
227    console.info('asset height: ', asset.get(photoAccessHelper.PhotoKeys.HEIGHT));
228    console.info('asset title: ' + asset.get(photoAccessHelper.PhotoKeys.TITLE));
229    // 获取缩略图
230    asset.getThumbnail((err, pixelMap) => {
231      if (err == undefined) {
232        console.info('getThumbnail successful ' + JSON.stringify(pixelMap));
233      } else {
234        console.error('getThumbnail fail', err);
235      }
236    });
237  } catch (error){
238    console.error(`uriGetAssets failed with err, code is ${error.code}, message is ${error.message}`);
239  }
240}
241```
242<!--Del-->
243## 通过URI复制文件(仅对系统应用开放)
244
245用户复制文件到指定目录
246
2471. 通过[createFileAccessHelper](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#fileaccesscreatefileaccesshelper)创建fileAccessHelper helper。
248
2492. 获取源文件的srcUri。
250
2513. 获取目的路径的destUri。
252
2534. 获取备用名 fileName。
254
2555. 使用helper.[copyFile](../reference/apis-core-file-kit/js-apis-fileAccess-sys.md#copyfile11)(srcUri, destUri, fileName) 进行文件操作。
256
257复制文件代码示例:
258
259```ts
260import { BusinessError } from '@kit.BasicServicesKit';
261import { Want } from '@kit.AbilityKit';
262import { common } from '@kit.AbilityKit';
263import { fileAccess } from '@kit.CoreFileKit';
264
265// context 是EntryAbility 传过来的context,确保this.getUIContext().getHostContext()返回结果为UIAbilityContext
266let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
267async function example(context: common.UIAbilityContext) {
268    let fileAccessHelper: fileAccess.FileAccessHelper;
269    // wantInfos 从getFileAccessAbilityInfo()获取
270    let wantInfos: Array<Want> = [
271      {
272        bundleName: "com.ohos.UserFile.ExternalFileManager",
273        abilityName: "FileExtensionAbility",
274      },
275    ]
276    try {
277      fileAccessHelper = fileAccess.createFileAccessHelper(context, wantInfos);
278      if (!fileAccessHelper) {
279        console.error("createFileAccessHelper interface returns an undefined object");
280      }
281      // 以内置存储目录为例
282      // 示例代码sourceUri表示Download目录,该URI是对应的fileInfo中URI
283      // 开发者应根据自己实际获取的URI进行开发
284      let sourceUri: string = "file://docs/storage/Users/currentUser/Download/one.txt";
285      // 将文件复制到的位置URI
286      let destUri: string = "file://docs/storage/Users/currentUser/Documents";
287      // 如果文件名冲突,要使用的文件名
288      let displayName: string = "file1.txt";
289      // 存放返回的URI
290      let fileUri: string;
291      try {
292        // 复制文件返回该文件的URI
293        fileUri = await fileAccessHelper.copyFile(sourceUri, destUri, displayName);
294        if (!fileUri) {
295          console.error("copyFile return undefined object");
296        }
297        console.info("copyFile success, fileUri: " + JSON.stringify(fileUri));
298      } catch (err) {
299        let error: BusinessError = err as BusinessError;
300        console.error("copyFile failed, errCode:" + error.code + ", errMessage:" + error.message);
301      }
302    } catch (err) {
303      let error: BusinessError = err as BusinessError;
304      console.error("createFileAccessHelper failed, errCode:" + error.code + ", errMessage:" + error.message);
305    }
306  }
307```
308<!--DelEnd-->