feat(app): 添加应用崩溃恢复功能并优化网络请求

- 新增 MyAbilityStage 类,实现应用崩溃恢复功能
- 在 ApiElem接口中添加 showLog 字段,用于控制请求日志输出
- 重构 HttpHelper 类,提取公共方法到 HttpHelperX 类
- 优化网络请求方法,增加日志输出和错误处理
- 新增 Base64Helper 和 CharHelper 工具类
这个提交包含在:
徐勤民 2024-10-31 12:23:46 +08:00
父节点 d7c1f85370
当前提交 9a2f82c33c
共有 13 个文件被更改,包括 2024 次插入131 次删除

查看文件

@ -4,6 +4,13 @@
export { ToolsHelper } from './src/main/ets/utils/ToolsHelper' export { ToolsHelper } from './src/main/ets/utils/ToolsHelper'
export { ToolsHelperForTS } from './src/main/ets/utils/ToolsHelperForTS' export { ToolsHelperForTS } from './src/main/ets/utils/ToolsHelperForTS'
export { AlgorithmHelper } from './src/main/ets/utils/AlgorithmHelper' export { AlgorithmHelper } from './src/main/ets/utils/AlgorithmHelper'
export { Base64Helper } from './src/main/ets/utils/Base64Helper'
export { CharHelper } from './src/main/ets/utils/CharHelper'
export { CrashHelper } from './src/main/ets/utils/CrashHelper'
export { FileHelper } from './src/main/ets/utils/FileHelper'
export { PickerHelper } from './src/main/ets/utils/PickerHelper'
export { StrHelper } from './src/main/ets/utils/StrHelper'
export { LogHelper } from './src/main/ets/utils/LogHelper'
/** /**
* 存储相关 * 存储相关

查看文件

@ -1,28 +1,11 @@
import { ArrayList, HashMap } from '@kit.ArkTS'; import { ArrayList, HashMap } from '@kit.ArkTS';
import http from '@ohos.net.http'; import http from '@ohos.net.http';
import { LogHelper } from '../../../../Index';
import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper'; import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper';
import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys'; import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys';
import { ToolsHelperForTS } from '../utils/ToolsHelperForTS'; import { HttpHelperX, HttpParamsForm, HttpParamsGet, HttpParamsPost } from './HttpHelperX';
type HttpParamsGet = {
url: string
query?: Record<string, string> | Object
headers?: Record<string, string>
}
type HttpParamsPost = {
url: string
data?: string | Object | ArrayBuffer
query?: Record<string, string> | Object
headers?: Record<string, string>
}
type HttpParamsForm = {
url: string
data?: Record<string, string> | Object|undefined
query?: Record<string, string> | Object
headers?: Record<string, string>
}
export class HttpHelper { export class HttpHelper {
private static instance: HttpHelper | null = null private static instance: HttpHelper | null = null
@ -51,7 +34,10 @@ export class HttpHelper {
* 添加并发白名单 * 添加并发白名单
* @param apiNo * @param apiNo
*/ */
public addConcurrent(apiNo: string) { public addConcurrent(apiNo?: string) {
if (!apiNo) {
return
}
if (this.concurrentList.getIndexOf(apiNo) === -1) { if (this.concurrentList.getIndexOf(apiNo) === -1) {
this.concurrentList.add(apiNo) this.concurrentList.add(apiNo)
} }
@ -70,7 +56,7 @@ export class HttpHelper {
* @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用 * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
* @returns * @returns
*/ */
public postJson<T>(params: HttpParamsPost, apiNo?: string): Promise<T> { public postJson<T>(params: HttpParamsPost, apiNo?: string, showLog?: boolean): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
@ -79,26 +65,25 @@ export class HttpHelper {
this.httpHandlerList.get(apiNo ?? params.url).destroy() this.httpHandlerList.get(apiNo ?? params.url).destroy()
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
let httpRequest = http.createHttp(); let httpRequest = http.createHttp();
if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) { if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) {
this.httpHandlerList.set(apiNo ?? params.url, httpRequest) this.httpHandlerList.set(apiNo ?? params.url, httpRequest)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
const header = { const header = HttpHelperX.getHeaders("application/json;charset=UTF-8", params.headers)
"Content-Type": "application/json;charset=UTF-8",
// "Accept": "application/json",
...params.headers
}
console.log('=====>', 'POST:', JSON.stringify(params))
// console.log('=====>', '接口请求', JSON.stringify(header))
// console.log('=====>', '接口请求', data)
httpRequest.request(this.getUrl(params.url, params.query), { if (showLog) {
LogHelper.debug(`postJson${apiNo}\n`, JSON.stringify(params))
}
httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
method: http.RequestMethod.POST, method: http.RequestMethod.POST,
connectTimeout: 20000, connectTimeout: 20000,
readTimeout: 20000, readTimeout: 20000,
@ -106,18 +91,16 @@ export class HttpHelper {
extraData: params.data extraData: params.data
}) })
.then((data: http.HttpResponse) => { .then((data: http.HttpResponse) => {
console.info(`=====>Result:${data.result as string}(${apiNo})`); if (showLog) {
// console.info('=====>' + 'code:' + data.responseCode); LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
// console.info('=====>' + 'type:' + JSON.stringify(data.resultType)); LogHelper.print(data)
// console.info('=====>' + 'header:' + JSON.stringify(data.header)); }
// console.info('=====>' + 'cookies:' + data.cookies); // 自API version 8开始支持cookie
// console.info('=====>' + 'header.content-Type:' + JSON.stringify(data.header));
// console.info('=====>' + 'header.Status-Line:' + JSON.stringify(data.header));
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (data.responseCode === 200) { if (data.responseCode === 200) {
resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T) resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
@ -128,11 +111,12 @@ export class HttpHelper {
reject(err) reject(err)
} }
}).catch((err: Error) => { }).catch((err: Error) => {
console.info('=====>' + 'Error:' + JSON.stringify({ err: err, url: params.url, })); LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (err.message === 'Failed writing received data to disk/application') { if (err.message === 'Failed writing received data to disk/application') {
reject('cancel') reject('cancel')
@ -151,7 +135,7 @@ export class HttpHelper {
* @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用 * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
* @returns * @returns
*/ */
public postForm<T>(params: HttpParamsForm, apiNo?: string): Promise<T> { public postForm<T>(params: HttpParamsForm, apiNo?: string, showLog?: boolean): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
@ -160,47 +144,43 @@ export class HttpHelper {
this.httpHandlerList.get(apiNo ?? params.url).destroy() this.httpHandlerList.get(apiNo ?? params.url).destroy()
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
let httpRequest = http.createHttp(); let httpRequest = http.createHttp();
if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) { if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) {
this.httpHandlerList.set(apiNo ?? params.url, httpRequest) this.httpHandlerList.set(apiNo ?? params.url, httpRequest)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
const header = { const header = HttpHelperX.getHeaders("application/x-www-form-urlencoded;charset=UTF-8", params.headers)
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", let data = HttpHelperX.getContent(params.data)
// "Accept": "application/json",
...params.headers if (showLog) {
LogHelper.debug(`postForm${apiNo}\n`, JSON.stringify(params))
} }
let data = this.getContent(params.data)
console.log('=====>', 'POSTForm:', params.url) httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
console.log('=====>', 'POSTForm:', JSON.stringify(header))
console.log('=====>', 'POSTForm:', data)
httpRequest.request(this.getUrl(params.url, params.query), {
method: http.RequestMethod.POST, method: http.RequestMethod.POST,
connectTimeout: 20000, connectTimeout: 20000,
readTimeout: 20000, readTimeout: 20000,
header: header, header: header,
extraData: data?encodeURI(data):undefined extraData: data ? encodeURI(data) : undefined
}) })
.then((data: http.HttpResponse) => { .then((data: http.HttpResponse) => {
console.info(`=====>Result:${data.result as string}(${apiNo})`); if (showLog) {
// console.info('=====>' + 'code:' + data.responseCode); LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
// console.info('=====>' + 'type:' + JSON.stringify(data.resultType)); LogHelper.print(data)
// console.info('=====>' + 'header:' + JSON.stringify(data.header)); }
// console.info('=====>' + 'cookies:' + data.cookies); // 自API version 8开始支持cookie
// console.info('=====>' + 'header.content-Type:' + JSON.stringify(data.header));
// console.info('=====>' + 'header.Status-Line:' + JSON.stringify(data.header));
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (data.responseCode === 200) { if (data.responseCode === 200) {
resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T) resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
@ -211,11 +191,12 @@ export class HttpHelper {
reject(err) reject(err)
} }
}).catch((err: Error) => { }).catch((err: Error) => {
console.info('=====>' + 'Error:' + JSON.stringify({ err: err, url: params.url, })); LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (err.message === 'Failed writing received data to disk/application') { if (err.message === 'Failed writing received data to disk/application') {
reject('cancel') reject('cancel')
@ -236,7 +217,7 @@ export class HttpHelper {
* @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用 * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
* @returns * @returns
*/ */
public get<T>(params: HttpParamsGet, apiNo?: string): Promise<T> { public get<T>(params: HttpParamsGet, apiNo?: string, showLog?: boolean): Promise<T> {
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
@ -245,42 +226,41 @@ export class HttpHelper {
this.httpHandlerList.get(apiNo ?? params.url).destroy() this.httpHandlerList.get(apiNo ?? params.url).destroy()
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
let httpRequest = http.createHttp(); let httpRequest = http.createHttp();
if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) { if (this.concurrentList.getIndexOf(apiNo ?? params.url) === -1) {
this.httpHandlerList.set(apiNo ?? params.url, httpRequest) this.httpHandlerList.set(apiNo ?? params.url, httpRequest)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
const header = { if (showLog) {
...params.headers LogHelper.debug(`GET${apiNo}\n`, HttpHelperX.getUrl(params.url, params.query) + '\n',
JSON.stringify(params.headers))
} }
console.log('=====>', 'GET:', this.getUrl(params.url, params.query))
console.log('=====>', 'header:', JSON.stringify(header))
httpRequest.request(this.getUrl(params.url, params.query), { httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
method: http.RequestMethod.GET, method: http.RequestMethod.GET,
connectTimeout: 20000, connectTimeout: 20000,
readTimeout: 20000, readTimeout: 20000,
header: header, header: params.headers,
// extraData: params.data // extraData: params.data
}) })
.then((data: http.HttpResponse) => { .then((data: http.HttpResponse) => {
console.info(`=====>Result:${data.result as string}(${apiNo})`); if (showLog) {
// console.info('=====>' + 'code:' + data.responseCode); LogHelper.debug(`${apiNo}:\n${data.result as string}`)
// console.info('=====>' + 'type:' + JSON.stringify(data.resultType)); LogHelper.print(data)
// console.info('=====>' + 'header:' + JSON.stringify(data.header)); }
// console.info('=====>' + 'cookies:' + data.cookies); // 自API version 8开始支持cookie
// console.info('=====>' + 'header.content-Type:' + JSON.stringify(data.header));
// console.info('=====>' + 'header.Status-Line:' + JSON.stringify(data.header));
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (data.responseCode === 200) { if (data.responseCode === 200) {
resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T) resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
@ -291,11 +271,12 @@ export class HttpHelper {
reject(err) reject(err)
} }
}).catch((err: Error) => { }).catch((err: Error) => {
console.info('=====>' + 'Error:' + JSON.stringify({ err: err, url: params.url, })); LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
if (this.httpHandlerList.hasKey(apiNo ?? params.url)) { if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
this.httpHandlerList.remove(apiNo ?? params.url) this.httpHandlerList.remove(apiNo ?? params.url)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length) SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
this.httpHandlerList.length)
} }
if (err.message === 'Failed writing received data to disk/application') { if (err.message === 'Failed writing received data to disk/application') {
reject('cancel') reject('cancel')
@ -306,42 +287,4 @@ export class HttpHelper {
}); });
} }
private getUrl(url: string, query?: Record<string, string> | Object) {
let u = url
if (query) {
let q = query
if (typeof query === 'object') {
q = ToolsHelperForTS.classToRecord(query)
}
u = `${u}${u.indexOf('?') < 0 ? '?' : u.endsWith('$') ? '' : '&'}`
Object.entries(q).forEach((row) => {
if (row[1]) {
u = `${u}${row[0]}=${row[1] as string}&`
}
});
u = u.slice(0, u.length - 1)
}
return u
}
private getContent(data?: Record<string, string> | Object) {
if (!data) {
return undefined
}
let u = ''
let q = data
if (typeof data === 'object') {
q = ToolsHelperForTS.classToRecord(data)
}
Object.entries(q).forEach((row) => {
if (row[1]) {
u = `${u}${row[0]}=${row[1] as string}&`
}
});
u = u.slice(0, u.length - 1)
return u
}
} }

查看文件

@ -0,0 +1,73 @@
import { ToolsHelperForTS } from '../utils/ToolsHelperForTS';
export interface HttpParamsGet {
url: string
query?: Record<string, string> | Object
headers?: Record<string, string | null | undefined>
}
export interface HttpParamsPost {
url: string
data?: string | Object | ArrayBuffer
query?: Record<string, string> | Object
headers?: Record<string, string | null | undefined>
}
export interface HttpParamsForm {
url: string
data?: Record<string, string> | Object | undefined
query?: Record<string, string> | Object
headers?: Record<string, string | null | undefined>
}
export class HttpHelperX {
/**
*
* @param ct Content-Type
* @param headers
* @returns
*/
static getHeaders(ct: string, headers?: Record<string, string>) {
return {
"Content-Type": ct,
// "Accept": "application/json",
...headers
}
}
static getUrl(url: string, query?: Record<string, string> | Object) {
let u = url
if (query) {
let q = query
if (typeof query === 'object') {
q = ToolsHelperForTS.classToRecord(query)
}
u = `${u}${u.indexOf('?') < 0 ? '?' : u.endsWith('$') ? '' : '&'}`
Object.entries(q).forEach((row) => {
if (row[1]) {
u = `${u}${row[0]}=${row[1] as string}&`
}
});
u = u.slice(0, u.length - 1)
}
return u
}
static getContent(data?: Record<string, string> | Object) {
if (!data) {
return undefined
}
let u = ''
let q = data
if (typeof data === 'object') {
q = ToolsHelperForTS.classToRecord(data)
}
Object.entries(q).forEach((row) => {
if (row[1]) {
u = `${u}${row[0]}=${row[1] as string}&`
}
});
u = u.slice(0, u.length - 1)
return u
}
}

查看文件

@ -0,0 +1,71 @@
import { util } from '@kit.ArkTS';
export class Base64Helper {
private constructor() {
}
/**
* 编码,通过输入参数编码后输出Uint8Array对象。
* @param array
* @returns
*/
static encode(array: Uint8Array): Promise<Uint8Array> {
let base64 = new util.Base64Helper();
return base64.encode(array);
}
/**
* 编码,通过输入参数编码后输出Uint8Array对象。
* @param array
* @returns
*/
static encodeSync(array: Uint8Array): Uint8Array {
let base64 = new util.Base64Helper();
let result = base64.encodeSync(array);
return result;
}
/**
* 编码,通过输入参数编码后输出对应文本。
* @param array
* @returns
*/
static encodeToStr(array: Uint8Array, options?: util.Type): Promise<string> {
let base64 = new util.Base64Helper();
return base64.encodeToString(array, options);
}
/**
* 编码,通过输入参数编码后输出对应文本。
* @param array
* @returns
*/
static encodeToStrSync(array: Uint8Array, options?: util.Type): string {
let base64 = new util.Base64Helper();
let result = base64.encodeToStringSync(array, options);
return result;
}
/**
* 解码,通过输入参数解码后输出对应Uint8Array对象。
* @param array
* @returns
*/
static decode(array: Uint8Array | string, options?: util.Type): Promise<Uint8Array> {
let base64 = new util.Base64Helper();
return base64.decode(array, options);
}
/**
* 解码,通过输入参数解码后输出对应Uint8Array对象。
* @param array
* @returns
*/
static decodeSync(array: Uint8Array | string, options?: util.Type): Uint8Array {
let base64 = new util.Base64Helper();
let result = base64.decodeSync(array, options);
return result;
}
}

查看文件

@ -0,0 +1,105 @@
import { i18n } from '@kit.LocalizationKit';
export class CharHelper {
private constructor() {
}
/**
* 判断字符串char是否是数字
* @param char
* @returns
*/
static isDigit(char: string): boolean {
return i18n.Unicode.isDigit(char);
}
/**
* 判断字符串char是否是字母
* @param char
* @returns
*/
static isLetter(char: string): boolean {
return i18n.Unicode.isLetter(char);
}
/**
* 判断字符串char是否是小写字母
* @param char
* @returns
*/
static isLowerCase(char: string): boolean {
return i18n.Unicode.isLowerCase(char);
}
/**
* 判断字符串char是否是大写字母
* @param char
* @returns
*/
static isUpperCase(char: string): boolean {
return i18n.Unicode.isUpperCase(char);
}
/**
* 判断字符串char是否是空格符
* @param char
* @returns
*/
static isSpaceChar(char: string): boolean {
return i18n.Unicode.isSpaceChar(char);
}
/**
* 判断字符串char是否是空白符
* @param char
* @returns
*/
static isWhitespace(char: string): boolean {
return i18n.Unicode.isWhitespace(char);
}
/**
* 判断字符串char是否是从右到左语言的字符
* @param char
* @returns
*/
static isRTL(char: string): boolean {
return i18n.Unicode.isRTL(char);
}
/**
* 判断字符串char是否是表意文字
* @param char
* @returns
*/
static isIdeograph(char: string): boolean {
return i18n.Unicode.isIdeograph(char);
}
/**
* 判断是否空白符 空白符包括空格、制表符、全角空格和不间断空格
* @param c
* @returns
*/
static isBlankChar(c: number): boolean {
return CharHelper.isWhitespace(c.toString())
|| CharHelper.isSpaceChar(c.toString())
|| c == 0xFEFF || c == 0x202A || c == 0x0000;
}
/**
* 判断字符是否位于ASCII范围内其中0-31是控制字符,32-127表示从A到Z的字母字符
* @param char 字符
* @returns
*/
static isAscii(char: string): boolean {
if (char.length == 1) { //确保输入的是单个字符
return char.charCodeAt(0) < 128;
} else {
return false;
}
}
}

查看文件

@ -0,0 +1,170 @@
import { appRecovery, common, errorManager, Want } from '@kit.AbilityKit';
import { TimeHelper } from './TimeHelper';
import { FileHelper } from './FileHelper';
import { PreferencesHelper } from './PreferencesHelper';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { StrHelper } from './StrHelper';
import { ToolsHelper } from './ToolsHelper';
import { PickerHelper } from './PickerHelper';
import { LogHelper } from './LogHelper';
export class CrashHelper {
private constructor() {
}
private static readonly idKey: string = 'crash_observer_id_key'
private static observerId: number = -100;
private static ErrorFilePath: string = ''; //错误日志文件路径
/**
* 注册错误观测器。注册后可以捕获到应用产生的js crash,应用崩溃时进程不会退出。将异常信息写入本地文件。
*/
static onError() {
try {
PreferencesHelper.get(CrashHelper.idKey).then(res => {
if (res !== undefined && (res as number) !== -100) {
CrashHelper.offError(); //如果存在,就先注销错误观测器。
}
CrashHelper.observerId = errorManager.on('error', {
onUnhandledException(errMsg) {
let errStr = `${TimeHelper.getTime()} - 异常信息:\n${errMsg}\n\n\n`;
LogHelper.error(errMsg)
CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt")
FileHelper.writeEasy(CrashHelper.ErrorFilePath, errStr);
},
onException(errObject) {
// let errStr = `${DateUtil.getTodayStr()} - 异常信息2\n${JSON.stringify(errObject)}\n\n\n`;
}
});
PreferencesHelper.put(CrashHelper.idKey, CrashHelper.observerId)
})
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `CrashHelper-onError-异常 ~ code: ${error.code} -·- message: ${error.message}`);
}
}
/**
* 注销错误观测器。
*/
static offError() {
try {
if (CrashHelper.observerId === -100) {
return
}
errorManager.off('error', CrashHelper.observerId, (err: BusinessError) => {
if (err) {
hilog.error(0x0000, '=====>', "CrashHelper" + JSON.stringify(err))
return;
}
PreferencesHelper.put(CrashHelper.idKey, -100)
})
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `CrashHelper-offError-异常 ~ code: ${error.code} -·- message: ${error.message}`);
}
}
/**
* 导出错误日志
*/
static onExportErrorLog() {
CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt")
if (StrHelper.isNotEmpty(CrashHelper.ErrorFilePath)) {
PickerHelper.saveDocument(['errorLog.txt']).then((documentSaveResult: Array<string>) => {
if (documentSaveResult && documentSaveResult.length > 0) {
let saveUri = documentSaveResult[0];
let file = FileHelper.openSync(saveUri);
FileHelper.copyFile(CrashHelper.ErrorFilePath, file.fd).then(() => {
FileHelper.close(file.fd);
});
}
})
} else {
ToolsHelper.showMessage('暂无日志文件')
}
}
/**
* 清空已有日志
*/
static clearErrorLog() {
FileHelper.unlinkSync(CrashHelper.ErrorFilePath)
CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt")
}
/**
* 读取错误日志文件
*/
static async readErrorText(): Promise<string> {
CrashHelper.ErrorFilePath = FileHelper.getFilesDirPath("ErrorLog", "errorLog.txt")
if (StrHelper.isNotEmpty(CrashHelper.ErrorFilePath)) {
if (FileHelper.accessSync(CrashHelper.ErrorFilePath)) {
return await FileHelper.readText(CrashHelper.ErrorFilePath);
}
}
return '';
}
/**
* 启用应用恢复功能,参数按顺序填入。该接口调用后,应用从启动器启动时第一个Ability支持恢复。
* @param restart RestartFlag 应用重启标志。
* ALWAYS_RESTART 0 总是重启应用。
* RESTART_WHEN_JS_CRASH 0x0001 发生JS_CRASH时重启应用。
* RESTART_WHEN_APP_FREEZE 0x0002 发生APP_FREEZE时重启应用。
* NO_RESTART 0xFFFF 总是不重启应用。
* @param saveOccasion SaveOccasionFlag 保存条件标志
* SAVE_WHEN_ERROR 0x0001 当发生应用故障时保存。
* SAVE_WHEN_BACKGROUND 0x0002 当应用切入后台时保存。
* @param saveMode SaveModeFlag 状态保存标志
* SAVE_WITH_FILE 0x0001 每次状态保存都会写入到本地文件缓存。
* SAVE_WITH_SHARED_MEMORY 0x0002 状态先保存在内存中,应用故障退出时写入到本地文件缓存。
*/
static enableAppRecovery(restart: appRecovery.RestartFlag = appRecovery.RestartFlag.ALWAYS_RESTART,
saveOccasion: appRecovery.SaveOccasionFlag = appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR,
saveMode: appRecovery.SaveModeFlag.SAVE_WITH_FILE = appRecovery.SaveModeFlag.SAVE_WITH_FILE) {
appRecovery.enableAppRecovery(restart, saveOccasion, saveMode);
}
/**
* 重启APP,并拉起应用启动时第一个Ability,可以配合errorManager相关接口使用。
* 如果该Ability存在已经保存的状态,这些状态数据会在Ability的OnCreate生命周期回调的want参数中作为wantParam属性传入。
* API10时将启动由setRestartWant指定的Ability。如果没有指定则按以下规则启动
* 如果当前应用前台的Ability支持恢复,则重新拉起该Ability。
* 如果存在多个支持恢复的Ability处于前台,则只拉起最后一个。
* 如果没有Ability处于前台,则不拉起。
*/
static restartApp() {
appRecovery.restartApp()
}
/**
* 设置下次恢复主动拉起场景下的Ability。该Ability必须为当前包下的UIAbility。
* @param want 通过设置Want中"bundleName"和"abilityName"字段来指定恢复重启的Ability。
*/
static setRestartWant(want: Want) {
appRecovery.setRestartWant(want);
}
/**
* 保存当前App状态 或 主动保存Ability的状态,这个状态将在下次恢复启动时使用。可以配合errorManager相关接口使用
* @param context UIAbilityContext 需要保存状态的UIAbility所对应的context。
* @returns
*/
static saveAppState(context?: common.UIAbilityContext): boolean {
if (context) {
return appRecovery.saveAppState(context) //主动保存Ability的状态
} else {
return appRecovery.saveAppState() //保存当前App状态
}
}
}

查看文件

@ -0,0 +1,812 @@
import fileUri from '@ohos.file.fileuri';
import fs, { ListFileOptions, ReadOptions, ReadTextOptions, WriteOptions } from '@ohos.file.fs';
import { BusinessError } from '@kit.BasicServicesKit';
import { StrHelper } from './StrHelper';
import { hilog } from '@kit.PerformanceAnalysisKit';
export class FileHelper {
private constructor() {
}
static readonly separator: string = '/';
/**
* 获取文件目录下的文件夹路径或文件路径。
* @param dirPath 文件路径;支持完整路径和相对路径download/wps/doc;dirPath传空字符串表示根目录
* @param fileName 文件名test.text;fileName传空字符串表示文件夹路径
* @param blHap trueHAP级别文件路径、 falseApp级别文件路径
* @returns
*/
static getFilesDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
let filePath = blHap ? getContext().filesDir : getContext().getApplicationContext().filesDir; //根目录
if (StrHelper.isNotEmpty(dirPath)) {
if (StrHelper.startsWith(dirPath, filePath)) { //路径中包含根目录,是完整路径。
filePath = dirPath;
} else { //路径中不包含根目录,拼接成完整路径。
filePath = filePath + FileHelper.separator + dirPath;
}
if (!FileHelper.accessSync(filePath)) {
FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
}
}
if (StrHelper.isNotEmpty(fileName)) {
filePath = filePath + FileHelper.separator + fileName;
}
return filePath;
}
/**
* 获取缓存目录下的文件夹路径或文件路径。
* @param dirPath 文件路径;支持完整路径和相对路径download/wps/doc;dirPath传空字符串表示根目录
* @param fileName 文件名test.text;fileName传空字符串表示文件夹路径
* @param blHap trueHAP级别文件路径、 falseApp级别文件路径
* @returns
*/
static getCacheDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
let filePath = blHap ? getContext().cacheDir : getContext().getApplicationContext().cacheDir; //根目录
if (StrHelper.isNotEmpty(dirPath)) {
if (FileHelper.hasDirPath(dirPath)) { //路径中包含根目录,是完整路径。
filePath = dirPath;
} else { //路径中不包含根目录,拼接成完整路径。
filePath = filePath + FileHelper.separator + dirPath;
}
if (!FileHelper.accessSync(filePath)) {
FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
}
}
if (StrHelper.isNotEmpty(fileName)) {
filePath = filePath + FileHelper.separator + fileName;
}
return filePath;
}
/**
* 获取临时目录下的文件夹路径或文件路径。
* @param dirPath 文件路径;支持完整路径和相对路径download/wps/doc;dirPath传空字符串表示根目录
* @param fileName 文件名test.text;fileName传空字符串表示文件夹路径
* @param blHap trueHAP级别文件路径、 falseApp级别文件路径
* @returns
*/
static getTempDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
let filePath = blHap ? getContext().tempDir : getContext().getApplicationContext().tempDir; //根目录
if (StrHelper.isNotEmpty(dirPath)) {
if (FileHelper.hasDirPath(dirPath)) { //路径中包含根目录,是完整路径。
filePath = dirPath;
} else { //路径中不包含根目录,拼接成完整路径。
filePath = filePath + FileHelper.separator + dirPath;
}
if (!FileHelper.accessSync(filePath)) {
FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
}
}
if (StrHelper.isNotEmpty(fileName)) {
filePath = filePath + FileHelper.separator + fileName;
}
return filePath;
}
/**
* 判断是否是完整路径
* @param path 文件路径
*/
static hasDirPath(path: string): boolean {
return StrHelper.startsWith(path, "/data/storage/el1/") || StrHelper.startsWith(path, "/data/storage/el2/");
}
/**
* 通过URI或路径,获取FileUri
* @param uriOrPath URI或路径
* @returns
*/
static getFileUri(uriOrPath: string): fileUri.FileUri {
return new fileUri.FileUri(uriOrPath);
}
/**
* 通过URI或路径,获取文件名。
* @param uriOrPath URI或路径
* @returns
*/
static getFileName(uriOrPath: string): string {
return FileHelper.getFileUri(uriOrPath).name;
}
/**
* 通过URI或路径,获取文件路径
* @param uriOrPath URI或路径
* @returns
*/
static getFilePath(uriOrPath: string): string {
return FileHelper.getFileUri(uriOrPath).path;
}
/**
* 通过URI或路径,获取对应文件父目录的URI。
* @param uriOrPath URI或路径
*/
static getParentUri(uriOrPath: string): string {
return FileHelper.getFileUri(uriOrPath).getFullDirectoryUri();
}
/**
* 通过URI或路径,获取对应文件父目录的路径名。
* @param uriOrPath URI或路径
*/
static getParentPath(uriOrPath: string): string {
let parentUri = FileHelper.getParentUri(uriOrPath);
return FileHelper.getFilePath(parentUri)
}
/**
* 以同步方法获取文件URI。
* @param path 应用沙箱路径
* @returns
*/
static getUriFromPath(path: string): string {
return fileUri.getUriFromPath(path);
}
/**
* 根据文件名获取文件后缀
* @param fileName 例如: test.txt test.doc
* @returns
*/
static getFileExtention(fileName: string) {
if (StrHelper.isNotEmpty(fileName) && fileName.includes(".")) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
return '';
}
/**
* 获取指定文件夹下所有文件的大小或指定文件大小。
* @param path 文件夹路径 或 文件路径
*/
static getFileDirSize(path: string): number {
if (FileHelper.accessSync(path)) { //path存在
if (FileHelper.isDirectory(path)) { //文件夹
let count: number = 0;
FileHelper.listFileSync(path, { recursion: true }).forEach((filePath) => {
count = count + FileHelper.lstatSync(path + filePath).size
})
return count;
} else { //文件
return FileHelper.lstatSync(path).size
}
}
return 0;
}
/**
* 判断文件是否是普通文件。
* @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
* @returns
*/
static isFile(file: string | number): boolean {
return fs.statSync(file).isFile();
}
/**
* 判断文件是否是目录。
* @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
* @returns
*/
static isDirectory(file: string | number): boolean {
return fs.statSync(file).isDirectory();
}
/**
* 重命名文件或文件夹,使用Promise异步回调。
* @param oldPath string 文件的应用沙箱原路径。
* @param newPath string 文件的应用沙箱新路径。
* @returns
*/
static rename(oldPath: string, newPath: string): Promise<void> {
return fs.rename(oldPath, newPath);
}
/**
* 重命名文件或文件夹,以同步方法。
* @param oldPath string 文件的应用沙箱原路径。
* @param newPath string 文件的应用沙箱新路径。
* @returns
*/
static renameSync(oldPath: string, newPath: string) {
fs.renameSync(oldPath, newPath);
}
/**
* 创建目录,当recursion指定为true,可多层级创建目录,使用Promise异步回调。
* @param path 目录的应用沙箱路径。
* @param recursion 是否多层级创建目录。recursion指定为true时,可多层级创建目录。recursion指定为false时,仅可创建单层目录。
* @returns
*/
static mkdir(path: string, recursion: boolean = true): Promise<void> {
if (recursion) {
return fs.mkdir(path, recursion);
} else {
return fs.mkdir(path);
}
}
/**
* 创建目录以同步方法,当recursion指定为true,可多层级创建目录。
* @param path 目录的应用沙箱路径。
* @param recursion 是否多层级创建目录。recursion指定为true时,可多层级创建目录。recursion指定为false时,仅可创建单层目录。
*/
static mkdirSync(path: string, recursion: boolean = true) {
if (recursion) {
fs.mkdirSync(path, recursion);
} else {
fs.mkdirSync(path);
}
}
/**
* 删除整个目录,使用Promise异步回调。
* @param path 目录的应用沙箱路径。
* @returns
*/
static rmdir(path: string): Promise<void> {
return fs.rmdir(path);
}
/**
* 删除整个目录,以同步方法。
* @param path 目录的应用沙箱路径。
*/
static rmdirSync(path: string) {
return fs.rmdirSync(path);
}
/**
* 删除单个文件,使用Promise异步回调。
* @param path 文件的应用沙箱路径。
* @returns
*/
static unlink(path: string): Promise<void> {
return fs.unlink(path);
}
/**
* 删除单个文件,以同步方法。
* @param path 文件的应用沙箱路径。
* @returns
*/
static unlinkSync(path: string) {
fs.unlinkSync(path);
}
/**
* 检查文件是否存在,使用Promise异步回调。
* @param path 文件应用沙箱路径。
* @returns
*/
static access(path: string): Promise<boolean> {
return fs.access(path);
}
/**
* 检查文件是否存在,以同步方法。
* @param path 文件应用沙箱路径。
* @returns
*/
static accessSync(path: string): boolean {
return fs.accessSync(path);
}
/**
* 打开文件,支持使用URI打开文件。使用Promise异步回调。
* @param path string 文件的应用沙箱路径或URI。
* @param mode number 打开文件的选项,必须指定如下选项中的一个,默认以只读方式打开。
* @returns
*/
static open(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): Promise<fs.File> {
return fs.open(path, mode);
}
/**
* 打开文件,支持使用URI打开文件。以同步方法。
* @param path string 文件的应用沙箱路径或URI。
* @param mode number 打开文件的选项,必须指定如下选项中的一个,默认以只读方式打开。
* @returns
*/
static openSync(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): fs.File {
return fs.openSync(path, mode);
}
/**
* 从文件读取数据,使用Promise异步回调。
* @param fd number 已打开的文件描述符。
* @param buffer ArrayBuffer 用于保存读取到的文件数据的缓冲区。
* @param options 支持如下选项:
* offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读。
* length,number类型,表示期望读取数据的长度。可选,默认缓冲区长度。
* @returns
*/
static read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise<number> {
return fs.read(fd, buffer, options)
}
/**
* 从文件读取数据,以同步方法。
* @param fd number 已打开的文件描述符。
* @param buffer ArrayBuffer 用于保存读取到的文件数据的缓冲区。
* @param options 支持如下选项:
* offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读。
* length,number类型,表示期望读取数据的长度。可选,默认缓冲区长度。
* @returns
*/
static readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number {
return fs.readSync(fd, buffer, options)
}
/**
* 基于文本方式读取文件即直接读取文件的文本内容,使用Promise异步回调。
* @param filePath 文件的应用沙箱路径。
* @param options 支持如下选项:
* offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读取。
* length,number类型,表示期望读取数据的长度。可选,默认文件长度。
* encoding,string类型,当数据是 string 类型时有效,表示数据的编码方式,默认 'utf-8',仅支持 'utf-8'。
* @returns
*/
static readText(filePath: string, options?: ReadTextOptions): Promise<string> {
return fs.readText(filePath, options);
}
/**
* 基于文本方式读取文件(即直接读取文件的文本内容),以同步方法。
* @param filePath 文件的应用沙箱路径。
* @param options 支持如下选项:
* offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读取。
* length,number类型,表示期望读取数据的长度。可选,默认文件长度。
* encoding,string类型,当数据是 string 类型时有效,表示数据的编码方式,默认 'utf-8',仅支持 'utf-8'。
* @returns
*/
static readTextSync(filePath: string, options?: ReadTextOptions): string {
return fs.readTextSync(filePath, options);
}
/**
* 将数据写入文件,使用Promise异步回调。
* @param fd number 已打开的文件描述符。
* @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
* @param options 支持如下选项:
* offset,number类型,表示期望写入文件的位置。可选,默认从当前位置开始写。
* length,number类型,表示期望写入数据的长度。可选,默认缓冲区长度。
* encoding,string类型,当数据是string类型时有效,表示数据的编码方式,默认 'utf-8'。当前仅支持 'utf-8'。
* @returns
*/
static write(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): Promise<number> {
return fs.write(fd, buffer, options)
}
/**
* 将数据写入文件,以同步方法。
* @param fd number 已打开的文件描述符。
* @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
* @param options 支持如下选项:
* offset,number类型,表示期望写入文件的位置。可选,默认从当前位置开始写。
* length,number类型,表示期望写入数据的长度。可选,默认缓冲区长度。
* encoding,string类型,当数据是string类型时有效,表示数据的编码方式,默认 'utf-8'。当前仅支持 'utf-8'。
* @returns
*/
static writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): number {
return fs.writeSync(fd, buffer, options)
}
/**
* 将数据写入文件,并关闭文件。
* @param path string 文件的应用沙箱路径或URI。
* @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
* @param append 是否追加,true-追加,false-不追加(直接覆盖)
* @returns
*/
static async writeEasy(path: string, buffer: ArrayBuffer | string, append: boolean = true): Promise<number> {
try {
let file = FileHelper.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let offset = append ? FileHelper.statSync(file.fd).size : 0
let options: WriteOptions = { offset: offset, encoding: 'utf-8' };
return await FileHelper.write(file.fd, buffer, options).finally(() => {
FileHelper.close(file.fd); //关闭文件
});
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `FileHelper-writeEasy-异常 ~ code: ${error.code} -·- message: ${error.message}`)
return -1;
}
}
/**
* 关闭文件,使用Promise异步回调。
* @param file 已打开的File对象或已打开的文件描述符fd。
* @returns
*/
static close(file: fs.File | number): Promise<void> {
return fs.close(file);
}
/**
* 关闭文件,以同步方法。
* @param file 已打开的File对象或已打开的文件描述符fd。
*/
static closeSync(file: fs.File | number) {
fs.closeSync(file);
}
/**
* 列出文件夹下所有文件名,支持递归列出所有文件名包含子目录下,支持文件过滤,使用Promise异步回调。
* @param path string 文件夹的应用沙箱路径。
* @param options 文件过滤选项。默认不进行过滤。
* recursion boolean 是否递归子目录下文件名,默认为false。
* listNum number 列出文件名数量。当设置0时,列出所有文件,默认为0。
* filter Filter 文件过滤选项。当前仅支持后缀名匹配、文件名模糊查询、文件大小过滤、最近修改时间过滤。
* @returns
*/
static listFile(path: string, options?: ListFileOptions): Promise<string[]> {
return fs.listFile(path, options);
}
/**
* 列出文件夹下所有文件名,支持递归列出所有文件名(包含子目录下),支持文件过滤,以同步方法。
* @param path string 文件夹的应用沙箱路径。
* @param options 文件过滤选项。默认不进行过滤。
* recursion boolean 是否递归子目录下文件名,默认为false。
* listNum number 列出文件名数量。当设置0时,列出所有文件,默认为0。
* filter Filter 文件过滤选项。当前仅支持后缀名匹配、文件名模糊查询、文件大小过滤、最近修改时间过滤。
* @returns
*/
static listFileSync(path: string, options?: ListFileOptions): string[] {
return fs.listFileSync(path, options);
}
/**
* 获取文件详细属性信息,使用Promise异步回调。
* @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
*/
static stat(file: string | number): Promise<fs.Stat> {
return fs.stat(file);
}
/**
* 获取文件详细属性信息,以同步方法。
* @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
* @returns
*/
static statSync(file: string | number): fs.Stat {
return fs.statSync(file);
}
/**
* 拷贝文件或者目录,支持拷贝进度监听,使用Promise异步返回。
* @param srcUri 待复制文件或目录的uri。
* @param destUri 目标文件或目录的uri。
* @param options options中提供拷贝进度回调
* ProgressListener 拷贝进度监听。
* @returns
*/
static copy(srcUri: string, destUri: string, options?: fs.CopyOptions): Promise<void> {
return fs.copy(srcUri, destUri, options);
}
/**
* 复制文件,使用Promise异步回调。
* @param src string|number 待复制文件的路径或待复制文件的文件描述符。
* @param dest string|number 目标文件路径或目标文件的文件描述符。
* @param mode number 提供覆盖文件的选项,当前仅支持0,且默认为0。0完全覆盖目标文件。
* @returns
*/
static copyFile(src: string | number, dest: string | number, mode: number = 0): Promise<void> {
return fs.copyFile(src, dest, mode);
}
/**
* 以同步方法复制文件。
* @param src string|number 待复制文件的路径或待复制文件的文件描述符。
* @param dest string|number 目标文件路径或目标文件的文件描述符。
* @param mode number 提供覆盖文件的选项,当前仅支持0,且默认为0。0完全覆盖目标文件。
*/
static copyFileSync(src: string | number, dest: string | number, mode: number = 0) {
fs.copyFileSync(src, dest, mode);
}
/**
* 复制源文件夹至目标路径下,只能复制沙箱里的文件夹,使用Promise异步返回。
* @param src 源文件夹的应用沙箱路径。
* @param dest 目标文件夹的应用沙箱路径。
* @param mode 复制模式:
* mode为0,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
* mode为1,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
* @returns
*/
static copyDir(src: string, dest: string, mode: number = 1): Promise<void> {
return fs.copyDir(src, dest, mode);
}
/**
* 以同步方法复制源文件夹至目标路径下,只能复制沙箱里的文件夹。
* @param src 源文件夹的应用沙箱路径。
* @param dest 目标文件夹的应用沙箱路径。
* @param mode 复制模式:
* mode为0,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
* mode为1,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
* @returns
*/
static copyDirSync(src: string, dest: string, mode: number = 1) {
fs.copyDirSync(src, dest, mode);
}
/**
* 移动文件,使用Promise异步回调。
* @param src string 源文件的应用沙箱路径。
* @param dest string 目的文件的应用沙箱路径。
* @param mode number 移动模式。若mode为0,移动位置存在同名文件时,强制移动覆盖。若mode为1,移动位置存在同名文件时,抛出异常。默认为0。
* @returns
*/
static moveFile(src: string, dest: string, mode: number = 0): Promise<void> {
return fs.moveFile(src, dest, mode)
}
/**
* 移动文件,以同步方法。
* @param src string 源文件的应用沙箱路径。
* @param dest string 目的文件的应用沙箱路径。
* @param mode number 移动模式。若mode为0,移动位置存在同名文件时,强制移动覆盖。若mode为1,移动位置存在同名文件时,抛出异常。默认为0。
* @returns
*/
static moveFileSync(src: string, dest: string, mode: number = 0) {
fs.moveFileSync(src, dest, mode)
}
/**
* 移动源文件夹至目标路径下,使用Promise异步返回。
* @param src 源文件夹的应用沙箱路径
* @param dest 目标文件夹的应用沙箱路径
* @param mode 移动模式:
* mode为0,文件夹级别抛异常。若目标文件夹下存在与源文件夹名冲突的非空文件夹,则抛出异常。
* mode为1,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
* mode为2,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
* mode为3,文件夹级别强制覆盖。移动源文件夹至目标文件夹下,目标文件夹下移动的文件夹内容与源文件夹完全一致。若目标文件夹下存在与源文件夹名冲突的文件夹,该文件夹下所有原始文件将不会保留。
* @returns
*/
static moveDir(src: string, dest: string, mode: number = 3): Promise<void> {
return fs.moveDir(src, dest, mode);
}
/**
* 以同步方法移动源文件夹至目标路径下。
* @param src 源文件夹的应用沙箱路径
* @param dest 目标文件夹的应用沙箱路径
* @param mode 移动模式:
* mode为0,文件夹级别抛异常。若目标文件夹下存在与源文件夹名冲突的非空文件夹,则抛出异常。
* mode为1,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
* mode为2,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
* mode为3,文件夹级别强制覆盖。移动源文件夹至目标文件夹下,目标文件夹下移动的文件夹内容与源文件夹完全一致。若目标文件夹下存在与源文件夹名冲突的文件夹,该文件夹下所有原始文件将不会保留。
* @returns
*/
static moveDirSync(src: string, dest: string, mode: number = 3) {
return fs.moveDirSync(src, dest, mode);
}
/**
* 截断文件,使用Promise异步回调。
* @param file string|number 文件的应用沙箱路径或已打开的文件描述符fd。
* @param len number 文件截断后的长度,以字节为单位。默认为0。
* @returns
*/
static truncate(file: string | number, len: number = 0): Promise<void> {
return fs.truncate(file, len)
}
/**
* 截断文件,以同步方法。
* @param file string|number 文件的应用沙箱路径或已打开的文件描述符fd。
* @param len number 文件截断后的长度,以字节为单位。默认为0。
* @returns
*/
static truncateSync(file: string | number, len: number = 0) {
fs.truncateSync(file, len)
}
/**
* 获取链接文件信息,使用Promise异步回调。
* @param path string 文件的应用沙箱路径。
* @returns
*/
static lstat(path: string): Promise<fs.Stat> {
return fs.lstat(path);
}
/**
* 获取链接文件信息,以同步方法。
* @param path string 文件的应用沙箱路径。
* @returns
*/
static lstatSync(path: string): fs.Stat {
return fs.lstatSync(path);
}
/**
* 同步文件数据,使用Promise异步回调。
* @param fd number 已打开的文件描述符。
* @returns
*/
static fsync(fd: number): Promise<void> {
return fs.fsync(fd);
}
/**
* 同步文件数据,以同步方法。
* @param fd number 已打开的文件描述符。
*/
static fsyncSync(fd: number) {
fs.fsyncSync(fd);
}
/**
* 实现文件内容数据同步,使用Promise异步回调。
* @param fd number 已打开的文件描述符。
* @returns
*/
static fdatasync(fd: number): Promise<void> {
return fs.fdatasync(fd);
}
/**
* 实现文件内容数据同步,以同步方法。
* @param fd number 已打开的文件描述符。
*/
static fdatasyncSync(fd: number) {
fs.fdatasyncSync(fd);
}
/**
* 基于文件路径打开文件流,使用Promise异步回调。
* @param path string 文件的应用沙箱路径。
* @param mode string 文件打开类型
* r打开只读文件,该文件必须存在。
* r+:打开可读写的文件,该文件必须存在。
* w打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* w+打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
* a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
* @returns
*/
static createStream(path: string, mode: string = 'r'): Promise<fs.Stream> {
return fs.createStream(path, mode)
}
/**
* 基于文件路径打开文件流,以同步方法。
* @param path string 文件的应用沙箱路径。
* @param mode string 文件打开类型
* r打开只读文件,该文件必须存在。
* r+:打开可读写的文件,该文件必须存在。
* w打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* w+打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
* a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
* @returns
*/
static createStreamSync(path: string, mode: string = 'r'): fs.Stream {
return fs.createStreamSync(path, mode);
}
/**
* 基于文件描述符打开文件流,使用Promise异步回调。
* @param fd number 已打开的文件描述符。
* @param mode string 文件打开类型
* r打开只读文件,该文件必须存在。
* r+:打开可读写的文件,该文件必须存在。
* w打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* w+打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
* a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
* @returns
*/
static fdopenStream(fd: number, mode: string = 'r'): Promise<fs.Stream> {
return fs.fdopenStream(fd, mode)
}
/**
* 基于文件描述符打开文件流,以同步方法。
* @param fd number 已打开的文件描述符。
* @param mode string 文件打开类型
* r打开只读文件,该文件必须存在。
* r+:打开可读写的文件,该文件必须存在。
* w打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* w+打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
* a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
* a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
* @returns
*/
static fdopenStreamSync(fd: number, mode: string = 'r'): fs.Stream {
return fs.fdopenStreamSync(fd, mode)
}
/**
* 创建临时目录,使用Promise异步回调。
* @param prefix string 用随机产生的字符串替换以“XXXXXX”结尾目录路径。
* @returns
*/
static mkdtemp(prefix: string): Promise<string> {
return fs.mkdtemp(prefix);
}
/**
* 创建临时目录,以同步的方法。
* @param prefix string 用随机产生的字符串替换以“XXXXXX”结尾目录路径。
* @returns
*/
static mkdtempSync(prefix: string): string {
return fs.mkdtempSync(prefix);
}
/**
* 将文件描述符转化为File。
* @param fd 文件描述符。
* @returns
*/
static dup(fd: number): fs.File {
return fs.dup(fd);
}
/**
* 修改文件最近访问时间属性。
* path 文件的应用沙箱路径。
* mtime 待更新的时间戳。自1970年1月1日起至目标时间的毫秒数。仅支持修改文件最近访问时间属性。
* @returns
*/
static utimes(path: string, mtime: number): void {
fs.utimes(path, mtime);
}
/**
* 格式化文件大小
* @param fileSize
* @returns
*/
static getFormatFileSize(fileSize: number): string {
if (fileSize < 1024) {
return fileSize + "B";
} else if (fileSize < 1024 * 1024) {
return (fileSize / 1024).toFixed(1) + "KB";
} else if (fileSize < 1024 * 1024 * 1024) {
return (fileSize / (1024 * 1024)).toFixed(1) + "MB";
} else if (fileSize < 1024 * 1024 * 1024 * 1024) {
return (fileSize / (1024 * 1024 * 1024)).toFixed(1) + "GB";
} else {
return (fileSize / (1024 * 1024 * 1024 * 1024)).toFixed(1) + "TB";
}
}
}

查看文件

@ -0,0 +1,134 @@
import hilog from '@ohos.hilog'
import { BusinessError } from '@kit.BasicServicesKit'
const LOGGER_DOMAIN: number = 0x0000
const LOGGER_TAG: string = '=====》'
export class LogHelper {
private static domain: number = LOGGER_DOMAIN
private static tag: string = LOGGER_TAG //日志Tag
private static format: string = '%{public}s'
private static showLog: boolean = true //是否显示打印日志
/**
* 初始化日志参数该方法建议在Ability里调用
* @param domain
* @param tag
* @param showLog
*/
static init(domain: number = LOGGER_DOMAIN, tag: string = LOGGER_TAG, showLog: boolean = true) {
LogHelper.domain = domain
LogHelper.tag = tag
LogHelper.showLog = showLog
}
/**
* 设置日志对应的领域标识,范围是0x0~0xFFFF。该方法建议在Ability里调用
* @param domain
*/
static setDomain(domain: number = LOGGER_DOMAIN) {
LogHelper.domain = domain
}
/**
* 设置日志标识该方法建议在Ability里调用
* @param tag
*/
static setTag(tag: string = LOGGER_TAG) {
LogHelper.tag = tag
}
/**
* 是否打印日志该方法建议在Ability里调用
* @param showLog
*/
static setShowLog(showLog: boolean = true) {
LogHelper.showLog = showLog
}
/**
* 打印DEBUG级别日志
* @param args
*/
static debug(...args: string[]): void {
if (LogHelper.showLog) {
hilog.debug(LogHelper.domain, LogHelper.tag, ' ')
hilog.debug(LogHelper.domain, LogHelper.tag, LogHelper.format.repeat(args.length), args)
}
}
/**
* 打印INFO级别日志
* @param args
*/
static info(...args: string[]): void {
if (LogHelper.showLog) {
hilog.info(LogHelper.domain, LogHelper.tag, ' ')
hilog.info(LogHelper.domain, LogHelper.tag, LogHelper.format.repeat(args.length), args)
}
}
/**
* 打印WARN级别日志
* @param args
*/
static warn(...args: string[]): void {
if (LogHelper.showLog) {
hilog.warn(LogHelper.domain, LogHelper.tag, ' ')
hilog.warn(LogHelper.domain, LogHelper.tag, LogHelper.format.repeat(args.length), args)
}
}
/**
* 打印ERROR级别日志
* @param args
*/
static error(...args: string[]): void {
if (LogHelper.showLog) {
hilog.error(LogHelper.domain, LogHelper.tag, ' ')
hilog.error(LogHelper.domain, LogHelper.tag, LogHelper.format.repeat(args.length), args)
}
}
/**
* 打印FATAL级别日志
* @param args
*/
static fatal(...args: string[]): void {
if (LogHelper.showLog) {
hilog.fatal(LogHelper.domain, LogHelper.tag, ' ')
hilog.fatal(LogHelper.domain, LogHelper.tag, LogHelper.format.repeat(args.length), args)
}
}
/**
* 打印JSON对象和JSON字符串
* @param obj
*/
static print(obj: object | string) {
try {
console.debug('')
if (typeof obj === 'object') {
let str = JSON.stringify(obj, null, 2)
let arr: string[] = str.split('\n')
for (let index = 0; index < arr.length; index++) {
console.debug(arr[index])
}
} else {
obj = JSON.parse(obj)
let str = JSON.stringify(obj, null, 2)
let arr = str.split('\n')
for (let index = 0; index < arr.length; index++) {
console.debug(arr[index])
}
}
} catch (err) {
let error = err as BusinessError; //异常了,说明不是JSON字符串
LogHelper.error(`LogHelper-print-异常 ~ code: ${error.code} -·- message: ${error.message}`);
}
}
}
// export default new LogHelper() //单例在ES6模块中,当你使用 import 导入一个模块时,实际上是在导入该模块的值的一个引用。这意味着在另一个模块中修改该值会影响原始模块中的值。)

查看文件

@ -0,0 +1,219 @@
import picker from '@ohos.file.picker';
import { camera, cameraPicker } from '@kit.CameraKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOCUMENT_DEFAULT_SELECT_NUMBER: number = 9; //数量
export class PickerHelper {
private constructor() {
}
/**
* 调用系统相机,拍照、录视频
* @param options
* @returns
*/
static async camera(options?: CameraOptions): Promise<string> {
try {
if (!options) {
options = new CameraOptions();
}
if (!options.mediaTypes || options.mediaTypes.length == 0) {
options.mediaTypes = [cameraPicker.PickerMediaType.PHOTO, cameraPicker.PickerMediaType.VIDEO];
}
let pickerProfile: cameraPicker.PickerProfile = {
cameraPosition: options.cameraPosition ? options.cameraPosition : camera.CameraPosition.CAMERA_POSITION_BACK,
videoDuration: options.videoDuration,
saveUri: options.saveUri
};
let context = getContext() as common.Context;
let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(context,
options.mediaTypes, pickerProfile);
if (pickerResult && pickerResult.resultUri) {
return pickerResult.resultUri;
}
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `PickerHelper-camera-异常 ~ code: ${error.code} -·- message: ${error.message}`);
}
return "";
}
/**
* 通过选择模式拉起PhotoViewPicker界面,用户可以选择一个或多个图片/视频。
* @param options
* @returns
*/
static async selectPhoto(options?: picker.PhotoSelectOptions): Promise<Array<string>> {
try {
if (!options) {
options = new picker.PhotoSelectOptions();
}
if (!options.MIMEType) { //可选择的媒体文件类型,若无此参数,则默认为图片和视频类型。
options.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
}
if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
options.maxSelectNumber = DOCUMENT_DEFAULT_SELECT_NUMBER;
}
let photoPicker = new picker.PhotoViewPicker();
let photoSelectResult: picker.PhotoSelectResult = await photoPicker.select(options);
if (photoSelectResult && photoSelectResult.photoUris && photoSelectResult.photoUris.length > 0) {
return photoSelectResult.photoUris;
} else {
return [];
}
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>',
`PickerHelper-selectPhoto-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
/**
* 通过保存模式拉起photoPicker进行保存图片或视频资源的文件名,若无此参数,则默认需要用户自行输入
* @param newFileNames
*/
static async savePhoto(newFileNames?: Array<string>): Promise<Array<string>> {
try {
let photoPicker = new picker.PhotoViewPicker();
if (newFileNames == undefined || newFileNames == null || newFileNames.length == 0) {
let photoSaveResult = await photoPicker.save();
if (photoSaveResult && photoSaveResult.length > 0) {
return photoSaveResult;
} else {
return [];
}
} else {
let PhotoSaveOptions = new picker.PhotoSaveOptions();
PhotoSaveOptions.newFileNames = newFileNames;
let photoSaveResult = await photoPicker.save(PhotoSaveOptions);
if (photoSaveResult && photoSaveResult.length > 0) {
return photoSaveResult;
} else {
return [];
}
}
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `PickerHelper-savePhoto-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
/**
* 通过选择模式拉起documentPicker界面,用户可以选择一个或多个文件。
* @param options
* @returns
*/
static async selectDocument(options?: picker.DocumentSelectOptions): Promise<Array<string>> {
try {
if (!options) {
options = new picker.DocumentSelectOptions();
}
if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
options.maxSelectNumber = DOCUMENT_DEFAULT_SELECT_NUMBER;
}
if (!options.selectMode) { //支持选择的资源类型,默认文件
options.selectMode = picker.DocumentSelectMode.FILE;
}
let documentPicker = new picker.DocumentViewPicker();
return await documentPicker.select(options);
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>',
`PickerHelper-selectDocument-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
/**
* 通过保存模式拉起documentPicker界面,用户可以保存一个或多个文件。
* @param options
* @returns
*/
static async saveDocument(newFileNames?: Array<string>): Promise<Array<string>> {
try {
let documentPicker = new picker.DocumentViewPicker();
if (newFileNames == undefined || newFileNames == null || newFileNames.length == 0) {
return await documentPicker.save();
} else {
let documentSaveOptions = new picker.DocumentSaveOptions();
documentSaveOptions.newFileNames = newFileNames;
return await documentPicker.save(documentSaveOptions);
}
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>',
`PickerHelper-saveDocument-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
/**
* 通过选择模式拉起audioPicker界面目前拉起的是documentPicker,audioPicker在规划中,用户可以选择一个或多个音频文件。
* @returns
*/
static async selectAudio(options?: picker.AudioSelectOptions): Promise<Array<string>> {
try {
if (!options) {
options = new picker.AudioSelectOptions();
}
if (!options.maxSelectNumber) { //选择媒体文件数量的最大值,默认9
options.maxSelectNumber = DOCUMENT_DEFAULT_SELECT_NUMBER;
}
let audioPicker = new picker.AudioViewPicker();
return await audioPicker.select(options);
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>',
`PickerHelper-selectAudio-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
/**
* 通过保存模式拉起audioPicker界面目前拉起的是documentPicker,audioPicker在规划中,用户可以保存一个或多个音频文件。
* @param newFileNames
* @returns
*/
static async saveAudio(newFileNames?: Array<string>): Promise<Array<string>> {
try {
let audioPicker = new picker.AudioViewPicker();
if (newFileNames == undefined || newFileNames == null || newFileNames.length == 0) {
return await audioPicker.save();
} else {
let AudioSaveOptions = new picker.AudioSaveOptions();
AudioSaveOptions.newFileNames = newFileNames;
return await audioPicker.save(AudioSaveOptions);
}
} catch (err) {
let error = err as BusinessError;
hilog.error(0x0000, '=====>', `PickerHelper-saveAudio-异常 ~ code: ${error.code} -·- message: ${error.message}`);
return [];
}
}
}
/**
* 相机参数类
*/
export class CameraOptions {
mediaTypes: Array<cameraPicker.PickerMediaType> =
[cameraPicker.PickerMediaType.PHOTO, cameraPicker.PickerMediaType.VIDEO]; //媒体类型。
cameraPosition: camera.CameraPosition = camera.CameraPosition.CAMERA_POSITION_BACK; //相机的位置。
saveUri?: string; //保存配置信息的uri。
videoDuration?: number; //录制的最大时长。
}

查看文件

@ -0,0 +1,347 @@
import { CharHelper } from './CharHelper';
import { buffer, util } from '@kit.ArkTS';
import { Base64Helper } from './Base64Helper';
export class StrHelper {
private constructor() {
}
/**
* 判断字符串是否为空(undefined、null)
* @param str 被检测的字符串
* @returns 是否为空
*/
static isNull(str: string | undefined | null): boolean {
return str == undefined || str == null;
}
/**
* 判断字符串是否为非空。true为非空空,否则false
* @param str
* @returns
*/
static isNotNull(str: string | undefined | null): boolean {
return false == StrHelper.isNull(str);
}
/**
* 判断字符串是否为空(undefined、null、字符串长度为0)
* @param str 被检测的字符串
* @return 是否为空
*/
static isEmpty(str: string | undefined | null): boolean {
return str == undefined || str == null || str.length == 0;
}
/**
* 判断字符串是否为非空。true为非空空,否则false
* @param str
* @returns
*/
static isNotEmpty(str: string | undefined | null): boolean {
return false == StrHelper.isEmpty(str);
}
/**
* 判断字符串是否为空和空白符(空白符包括空格、制表符、全角空格和不间断空格)。true为空,否则false
* @param str
* @returns
*/
static isBlank(str: string | undefined | null): boolean {
let length: number = 0;
if ((str == undefined) || (str == null) || ((length = str.length) == 0)) {
return true;
}
for (let i = 0; i < length; i++) {
if (false == CharHelper.isBlankChar(str.charCodeAt(i))) {
return false; //只要有一个非空字符即为非空字符串
}
}
return true;
}
/**
* 判断字符串是否为非空和空白符(空白符包括空格、制表符、全角空格和不间断空格)true为非空,否则false
* @param str
* @returns
*/
static isNotBlank(str: string | undefined | null): boolean {
return false == StrHelper.isBlank(str);
}
/**
* 格式化字符串
* @param source
* @param defaultValue
* @returns
*/
static toStr(source: string | null | undefined, defaultValue = ""): string {
if (source == null || source == undefined) {
return defaultValue;
}
return String(source);
}
/**
* 替换字符串中匹配的正则为给定的字符串
* @param str 待替换的字符串
* @param pattern 要匹配的内容正则或字符串
* @param replaceValue 替换的内容
* @returns
*/
static replace(str: string, pattern: RegExp | string, replaceValue: string = ''): string {
return str.replace(pattern, replaceValue);
}
/**
* 替换字符串中所有匹配的正则为给定的字符串
* @param str 待替换的字符串
* @param pattern 要匹配的内容正则或字符串
* @param replaceValue 替换的内容
* @returns 返回替换后的字符串
*/
static replaceAll(str: string, pattern: RegExp | string, replaceValue: string = ''): string {
return str.replaceAll(pattern, replaceValue);
}
/**
* 判断字符串是否以给定的字符串开头
* @param string 要检索的字符串
* @param target 要检索字符
* @param position 检索的位置
* @returns
*/
static startsWith(string: string = '', target: string, position: number = 0): boolean {
return string.startsWith(target, position);
}
/**
* 判断字符串是否以给定的字符串结尾
* @param str 要检索的字符串
* @param target 要检索字符
* @param position 检索的位置
* @returns
*/
static endsWith(str: string = '', target: string, position: number = str.length): boolean {
return str.endsWith(target, position);
}
/**
* 将字符串重复指定次数
* @param str 要重复的字符串
* @param n 重复的次数
* @returns
*/
static repeat(str: string = '', n: number = 1): string {
return str.repeat(n);
}
/**
* 将整个字符串转换为小写
* @param str 要转换的字符串
* @returns 返回小写的字符串
*/
static toLower(str: string = ''): string {
return str.toLowerCase();
}
/**
* 将整个字符串转换为大写
* @param str 要转换的字符串
* @returns 返回小写的字符串
*/
static toUpper(str: string = ''): string {
return str.toUpperCase();
}
/**
* 将字符串首字母转换为大写,剩下为小写
* @param str 待转换的字符串
* @returns 转换后的
*/
static capitalize(str: string = ''): string {
if (StrHelper.isNotEmpty(str)) {
const firstChar = str.charAt(0).toUpperCase();
const restChars = str.slice(1).toLowerCase();
return firstChar + restChars;
}
return '';
}
/**
* 判断两个传入的数值或者是字符串是否相等
* @param source
* @param target
* @returns
*/
static equal(source: string | number, target: string | number): boolean {
return source === target;
}
/**
* 判断两个传入的数值或者是字符串是否不相等
* @param source
* @param target
* @returns
*/
static notEqual(source: string | number, target: string | number): boolean {
return false == StrHelper.equal(source, target);
}
/**
* 字符串转Uint8Array
* @param src 字符串
* @returns Uint8Array
*/
public static strToUint8Array(src: string, encoding: buffer.BufferEncoding = 'utf-8'): Uint8Array {
let textEncoder = new util.TextEncoder(encoding);
let result = textEncoder.encodeInto(src);
return result;
}
/**
* Uint8Array转字符串
* @param src Uint8Array
* @returns 字符串
*/
static unit8ArrayToStr(src: Uint8Array, encoding: buffer.BufferEncoding = 'utf-8'): string {
let textDecoder = util.TextDecoder.create(encoding, { ignoreBOM: true })
let result = textDecoder.decodeWithStream(src, { stream: true });
return result;
}
/**
* 16进制字符串转换unit8Array
* @param hexStr
* @returns
*/
static strToHex(hexStr: string): Uint8Array {
return new Uint8Array(buffer.from(hexStr, 'hex').buffer);
}
/**
* 16进制unit8Array转字符串
* @param arr
* @returns
*/
static hexToStr(arr: Uint8Array): string {
return buffer.from(arr).toString('hex');
}
/**
* Bytes转字符串
* @param bytes
* @returns
*/
public static bytesToStr(bytes: Uint8Array): string {
let str = ""
for (let i = 0; i < bytes.length; i++) {
str += String.fromCharCode(bytes[i]);
}
return str;
}
/**
* 字符串转Bytes
* @param str
* @returns
*/
public static strToBytes(str: string): Uint8Array {
let bytes: number[] = new Array();
for (let i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i))
}
return new Uint8Array(bytes);
}
/**
* 字符串转Base64字符串
* @param src 字符串
* @returns
*/
static strToBase64(src: string): string {
let uint8Array = StrHelper.strToUint8Array(src);
let result = Base64Helper.encodeToStrSync(uint8Array);
return result;
}
/**
* Base64字符串转字符串
* @param base64Str Base64字符串
* @returns
*/
static base64ToStr(base64Str: string): string {
let uint8Array = Base64Helper.decodeSync(base64Str);
let result = StrHelper.unit8ArrayToStr(uint8Array);
return result;
}
/**
* 字符串转ArrayBuffer
* @param str
* @returns
*/
static strToBuffer(src: string, encoding: buffer.BufferEncoding = 'utf-8'): ArrayBuffer {
let buf = buffer.from(src, encoding);
return buf.buffer;
}
/**
* ArrayBuffer转字符串
* @param str
* @returns
*/
static bufferToStr(src: ArrayBuffer, encoding: buffer.BufferEncoding = 'utf-8'): string {
let buf = buffer.from(src);
let result = buf.toString(encoding);
return result;
}
/**
* ArrayBuffer转Uint8Array
* @param str
* @returns
*/
static bufferToUint8Array(src: ArrayBuffer): Uint8Array {
return new Uint8Array(src);
}
/**
* Uint8Array转ArrayBuffer
* @param str
* @returns
*/
static unit8ArrayToBuffer(src: Uint8Array): ArrayBuffer {
// return buffer.from(src).buffer;
return src.buffer as ArrayBuffer;
}
/**
* 获取系统错误码对应的详细信息
* @param errno 错误码
* @returns
*/
static getErrnoToString(errno: number): string {
return util.errnoToString(errno);
}
}

查看文件

@ -25,17 +25,20 @@ export class TimeHelper {
/** /**
* *
* @param formats * @param formats
* 'yyyy年MM月dd日' * 'yyyy-MM-dd HH:mm:ss'
*/ */
static getTime(format: string = 'yyyy-MM-dd HH:mm:ss') {
return TimeHelper.formatDate(new Date(),format)
}
static formatDate(date: Date, format: string) { static formatDate(date: Date, format: string) {
const replacements: { [key: string]: string } = { const replacements: { [key: string]: string } = {
YYYY: date.getFullYear().toString(), yyyy: date.getFullYear().toString(),
MM: String(date.getMonth() + 1).padStart(2, "0"), MM: String(date.getMonth() + 1).padStart(2, "0"),
DD: String(date.getDate()).padStart(2, "0"), dd: String(date.getDate()).padStart(2, "0"),
HH: String(date.getHours()).padStart(2, "0"), HH: String(date.getHours()).padStart(2, "0"),
mm: String(date.getMinutes()).padStart(2, "0"), mm: String(date.getMinutes()).padStart(2, "0"),
ss: String(date.getSeconds()).padStart(2, "0") ss: String(date.getSeconds()).padStart(2, "0")
}; };
return format.replace(/YYYY|MM|DD|HH|mm|ss/g, matched => replacements[matched]); return format.replace(/yyyy|MM|dd|HH|mm|ss/g, matched => replacements[matched]);
} }
} }

查看文件

@ -4,6 +4,7 @@ import { HashMap } from '@kit.ArkTS';
import { DeviceInfo } from '../bean/DeviceInfo'; import { DeviceInfo } from '../bean/DeviceInfo';
import { common } from '@kit.AbilityKit'; import { common } from '@kit.AbilityKit';
import { md5_hex } from '../util/md5'; import { md5_hex } from '../util/md5';
import { LogHelper } from '../../../../Index';
export interface Btn { export interface Btn {
text?: string | Resource; text?: string | Resource;
@ -105,7 +106,7 @@ export class ToolsHelper {
*/ */
static log(...args: ESObject[]) { static log(...args: ESObject[]) {
const k = ToolsHelper.getStackKey()?.split('/') const k = ToolsHelper.getStackKey()?.split('/')
console.log(`========>${k ? k[k.length-1].split('.')[0] : ''}::`, args, '\n') LogHelper.info(`${k ? k[k.length-1].split('.')[0] : ''}::\n`, ...args)
} }
/** /**
@ -349,7 +350,7 @@ export class ToolsHelper {
} }
private static getUniqueId(fun: Function): string { private static getUniqueId(fun: Function): string {
ToolsHelper.log(ToolsHelper.getStackKey()) // ToolsHelper.log(ToolsHelper.getStackKey())
if (!ToolsHelper.uniqueIdMap.has(fun)) { if (!ToolsHelper.uniqueIdMap.has(fun)) {
ToolsHelper.uniqueIdMap.set(fun, ToolsHelper.getUuid()); ToolsHelper.uniqueIdMap.set(fun, ToolsHelper.getUuid());
} }

查看文件

@ -1,4 +1,4 @@
import { HashMap } from "@kit.ArkTS"; import { HashMap } from '@kit.ArkTS';
/** /**
* ,ets里面不能用 * ,ets里面不能用
@ -18,7 +18,7 @@ export class ToolsHelperForTS {
return myMap; return myMap;
} }
public static classToRecord(obj: Object): Record<string, string> { public static classToRecord(obj: Object): Record<string, string> {
const record: Record<string, string> = {} as Record<string, string>; const record: Record<string, string> = {} as Record<string, string>;
for (const key in obj) { for (const key in obj) {
if (obj.hasOwnProperty(key)) { if (obj.hasOwnProperty(key)) {
@ -27,4 +27,12 @@ export class ToolsHelperForTS {
} }
return record; return record;
} }
static gets(headers?: Record<string, string>) {
return {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
// "Accept": "application/json",
...headers
}
}
} }