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