• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import fileExtensionInfo from '@ohos.file.fileExtensionInfo';
17import fileAccess from '@ohos.file.fileAccess';
18import ObjectUtil from './ObjectUtil';
19import Logger from '../log/Logger';
20import StringUtil from './StringUtil';
21import { FILENAME_MAX_LENGTH,
22  RENAME_CONNECT_CHARACTER } from '../constants/Constant';
23import MediaLibrary from '@ohos.multimedia.mediaLibrary';
24
25const TAG = 'FileUtil';
26
27export class FileUtil {
28
29  /**
30   * uri 格式开头
31   */
32  static readonly URI_START = 'file://';
33
34  /**
35   * 根据fileAccess.FileInfo中的mode匹配是否是文件夹
36   * @param mode number
37   * @returns boolean
38   */
39  public static isFolder(mode: number): boolean {
40    return (mode & fileExtensionInfo.DocumentFlag.REPRESENTS_DIR) === fileExtensionInfo.DocumentFlag.REPRESENTS_DIR;
41  }
42
43  /**
44   * 计算文件夹子文件个数
45   * @param fileIterator fileAccess.FileIterator
46   * @returns number
47   */
48  public static getChildCountOfFolder(fileIterator: fileAccess.FileIterator): number {
49    let count = 0;
50    if (ObjectUtil.isNullOrUndefined(fileIterator)) {
51      return count;
52    }
53    let isDone: boolean = false;
54    while (!isDone) {
55      let currItem = fileIterator.next();
56      isDone = currItem.done;
57      if (isDone) {
58        break;
59      }
60      count++;
61    }
62    return count;
63  }
64
65  /**
66   * 获取文件信息
67   * @param uri 文件uri
68   * @param fileAccessHelper fileAccess.FileAccessHelper
69   * @returns fileAccess.FileInfo
70   */
71  public static async getFileInfoByUri(uri: string, fileAccessHelper: fileAccess.FileAccessHelper): Promise<fileAccess.FileInfo> {
72    try {
73      return await fileAccessHelper.getFileInfoFromUri(uri);
74    } catch (err) {
75      Logger.e(TAG, 'getFileInfoByUri err: ' + JSON.stringify(err));
76    }
77    return null;
78  }
79
80  /**
81   * 获取文件信息
82   * @param relativePath 文件relativePath
83   * @param fileAccessHelper fileAccess.FileAccessHelper
84   * @returns fileAccess.FileInfo
85   */
86  public static async getFileInfoByRelativePath(relativePath: string, fileAccessHelper: fileAccess.FileAccessHelper): Promise<fileAccess.FileInfo> {
87    try {
88      return await fileAccessHelper.getFileInfoFromRelativePath(relativePath);
89    } catch (err) {
90      Logger.e(TAG, 'getFileInfoByRelativePath err: ' + JSON.stringify(err));
91    }
92    return null;
93  }
94
95  /**
96   * 根据uri获取文件夹子文件列表Iterator
97   * @param uri
98   * @param fileAccessHelper
99   * @returns FileIterator
100   */
101  public static async getFileIteratorByUri(uri: string, fileAccessHelper: fileAccess.FileAccessHelper): Promise<fileAccess.FileIterator> {
102    try {
103      let fileInfo = await fileAccessHelper.getFileInfoFromUri(uri);
104      return fileInfo.listFile();
105    } catch (err) {
106      Logger.e(TAG, 'getFileIteratorByUri err: ' + JSON.stringify(err));
107    }
108    return null;
109  }
110
111  public static getFileAccessHelper(context, wants): fileAccess.FileAccessHelper {
112    try {
113      return fileAccess.createFileAccessHelper(context, wants);
114    } catch (err) {
115      Logger.i(TAG, 'getFileAccessHelper err: ' + JSON.stringify(err));
116    }
117    return null;
118  }
119
120  public static async getFileAccessHelperAsync(context): Promise<fileAccess.FileAccessHelper> {
121    try {
122      let wants = await fileAccess.getFileAccessAbilityInfo();
123      return fileAccess.createFileAccessHelper(context, wants);
124    } catch (err) {
125      Logger.i(TAG, 'getFileAccessHelperAsync err: ' + JSON.stringify(err));
126    }
127    return null;
128  }
129
130  public static getParentRelativePath(relativePath: string): string {
131    let curPath = relativePath;
132    if (StringUtil.isEmpty(relativePath)) {
133      return '';
134    }
135
136    let index: number = curPath.lastIndexOf('/');
137    // 去掉最后一个'/'
138    if (index === curPath.length - 1) {
139      curPath = curPath.substr(0, index);
140    }
141    index = curPath.lastIndexOf('/');
142    if (index <= 0) {
143      return '';
144    }
145    return curPath.substr(0, index + 1);
146  }
147
148  public static getUsageHabitsKey(prefix: string, suffix: string): string {
149    return prefix + suffix.charAt(0).toLocaleUpperCase() + suffix.substring(1);
150  }
151
152  /**
153   * 是否是uri路径
154   * @param path 路径
155   * @returns 结果
156   */
157  public static isUriPath(path: string): boolean {
158    if (ObjectUtil.isNullOrUndefined(path)) {
159      return false;
160    }
161    return path.startsWith(this.URI_START);
162  }
163
164  /**
165   * 从目录下获取某个文件名的文件
166   * @param foldrUri 目录uri
167   * @param fileName 文件名
168   * return 结果
169   */
170  public static async getFileFromFolder(foldrUri: string, fileName, fileAccessHelper: fileAccess.FileAccessHelper): Promise<fileAccess.FileInfo> {
171    // 先将目录的信息查询出来
172    let fileInfo: fileAccess.FileInfo = await this.getFileInfoByUri(foldrUri, fileAccessHelper);
173    if (ObjectUtil.isNullOrUndefined(fileInfo)) {
174      return null;
175    }
176    // 构建目标目录下的同名文件的相对路径
177    const destFileRelativePath = fileInfo.relativePath + fileInfo.fileName + '/' + fileName;
178    // 根据相对路径查询相应的文件
179    return await this.getFileInfoByRelativePath(destFileRelativePath, fileAccessHelper);
180  }
181
182  /**
183   * 根据FileInfo获取当前文件的文件夹
184   *
185   * @param fileInfo 文件对象
186   * @returns 返回当前文件的文件夹
187   */
188  public static getCurrentFolderByFileInfo(fileInfo: fileAccess.FileInfo): string {
189    if (fileInfo !== null) {
190      let path = fileInfo.relativePath;
191      return FileUtil.getCurrentDir(path, FileUtil.isFolder(fileInfo.mode));
192    }
193    return "";
194  }
195
196  public static async createFolder(fileAccessHelper: fileAccess.FileAccessHelper, parentUri: string, name: string): Promise<{code, uri}> {
197    let uri: string = '';
198    let code: any;
199    try {
200      uri = await fileAccessHelper.mkDir(parentUri, name);
201    } catch (error) {
202      code = error.code;
203      Logger.e(TAG, 'createFolder error occurred:' + error.code + ', ' + error.message);
204    }
205    return {code: code, uri: uri};
206  }
207
208  public static async hardDelete(uri: string, mediaLibrary: MediaLibrary.MediaLibrary): Promise<boolean> {
209    if (ObjectUtil.isNullOrUndefined(mediaLibrary)) {
210      return false;
211    }
212    try {
213      await mediaLibrary.deleteAsset(uri);
214      return true;
215    } catch (e) {
216      Logger.e(TAG, 'hardDelete error: ' + JSON.stringify(e));
217    }
218    return false;
219  }
220
221  /**
222   * 重命名
223   * @param fileAccessHelper FileAccessHelper
224   * @param oldUri oldUri
225   * @param newName newName
226   * @returns {err, uri}
227   */
228  public static async rename(fileAccessHelper: fileAccess.FileAccessHelper, oldUri: string, newName: string): Promise<{err, uri}> {
229    let uri: string = '';
230    let err: any;
231    try {
232      uri = await fileAccessHelper.rename(oldUri, newName);
233    } catch (error) {
234      err = {code: error.code, message: error.message};
235      Logger.e(TAG, 'rename error occurred:' + error.code + ', ' + error.message);
236    }
237    return {err: err, uri: uri};
238  }
239
240  public static async createFile(fileAccessHelper: fileAccess.FileAccessHelper, parentUri: string, fileName: string): Promise<{err, uri}> {
241    let retUri: string = '';
242    let err: any;
243    try {
244      Logger.i(TAG, 'createFile ' + fileAccessHelper + '; ' + parentUri + " ; " + fileName);
245      retUri = await fileAccessHelper.createFile(parentUri, fileName);
246    } catch (e) {
247      Logger.e(TAG, 'createFile error: ' + e.code + ', ' + e.message);
248      err = {code: e.code, message: e.message};
249    }
250    return {err: err, uri: retUri};
251  }
252
253  public static hasSubFolder(loadPath: string, curFolderPath: string): boolean {
254    if (!StringUtil.isEmpty(loadPath)) {
255      if (!StringUtil.isEmpty(curFolderPath)) {
256        loadPath = FileUtil.getPathWithFileSplit(loadPath);
257        curFolderPath = FileUtil.getPathWithFileSplit(curFolderPath);
258        if (loadPath.startsWith(curFolderPath)) {
259          return true;
260        }
261      }
262    }
263    return false;
264  }
265
266  public static getPathWithFileSplit(path: string): string {
267    let fileSplit: string = '/';
268    if (path && !path.endsWith(fileSplit)) {
269      path = path + fileSplit;
270    }
271    return path;
272  }
273
274  public static loadSubFinish(loadPath: string, curFolderPath: string, maxLevel: number): boolean {
275    let fileSplit: string = '/';
276    if (!StringUtil.isEmpty(loadPath)) {
277      if (!loadPath.endsWith(fileSplit)) {
278        loadPath = loadPath + fileSplit;
279      }
280
281      let folders = curFolderPath.split(fileSplit);
282
283      if ((curFolderPath + fileSplit) === loadPath || folders.length >= maxLevel) {
284        return true;
285      }
286    }
287    return false;
288  }
289
290  public static renameFile(fileName: string, renameCount: number, suffix: string): string {
291    if (ObjectUtil.isNullOrUndefined(fileName)) {
292      return fileName;
293    }
294    let newName = fileName;
295    if (renameCount > 0) {
296      newName = fileName + RENAME_CONNECT_CHARACTER + renameCount;
297      let strLen = newName.length + suffix.length;
298      // 字符长度大于最大长度
299      if (strLen > FILENAME_MAX_LENGTH) {
300        // 计算需要裁剪的长度
301        let subLen = strLen - FILENAME_MAX_LENGTH + 1;
302        newName = fileName.substring(0, fileName.length - subLen) + RENAME_CONNECT_CHARACTER + renameCount;
303      }
304    }
305    return newName + suffix;
306  }
307
308  public static getFileNameReName(fileName: string): string[] {
309    if (StringUtil.isEmpty(fileName)) {
310      return null;
311    }
312    let index = fileName.lastIndexOf(RENAME_CONNECT_CHARACTER);
313    if (index === -1) {
314      return null;
315    }
316    let str = fileName.substring(index + 1, fileName.length);
317    let name = fileName.substring(0, index);
318    return [name, str];
319  }
320
321  public static getCurrentDir(path: string, isFolder: boolean): string {
322    if (isFolder) {
323      return path;
324    }
325    if (path) {
326      let index: number = path.lastIndexOf('/');
327      let len: number = path.length;
328      if (len > 1 && index > 1) {
329        return path.substring(0, index);
330      }
331    }
332    return path;
333  }
334
335  public static getUriPath(path: string): string {
336    if (path && FileUtil.isUriPath(path)) {
337      return path;
338    }
339    return null;
340  }
341}