重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度
Signed-off-by: Madixin <madixin@huawei.com>
This commit is contained in:
parent
0dd26b9e75
commit
6cbe5eadc5
|
@ -1,3 +1,7 @@
|
||||||
|
|
||||||
|
## 3.1.1-rc.0
|
||||||
|
- 重构代码:抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中,降低函数复杂度
|
||||||
|
|
||||||
## 3.1.0
|
## 3.1.0
|
||||||
- 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别
|
- 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别
|
||||||
- 修复加载错误图后未去请求排队队列中的请求
|
- 修复加载错误图后未去请求排队队列中的请求
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
"main": "index.ets",
|
"main": "index.ets",
|
||||||
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
|
"repository": "https://gitee.com/openharmony-tpc/ImageKnife",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "3.1.0",
|
"version": "3.1.1-rc.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/gpu_transform": "^1.0.2"
|
"@ohos/gpu_transform": "^1.0.2"
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,18 +18,13 @@ import { IJobQueue } from './utils/IJobQueue'
|
||||||
import List from '@ohos.util.List';
|
import List from '@ohos.util.List';
|
||||||
import LightWeightMap from '@ohos.util.LightWeightMap';
|
import LightWeightMap from '@ohos.util.LightWeightMap';
|
||||||
import { LogUtil } from './utils/LogUtil';
|
import { LogUtil } from './utils/LogUtil';
|
||||||
import buffer from '@ohos.buffer';
|
|
||||||
import { FileCache } from './utils/FileCache';
|
|
||||||
import fs from '@ohos.file.fs';
|
|
||||||
import { ImageKnife } from './ImageKnife';
|
import { ImageKnife } from './ImageKnife';
|
||||||
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
|
import { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
|
||||||
import http from '@ohos.net.http';
|
|
||||||
import image from '@ohos.multimedia.image';
|
import image from '@ohos.multimedia.image';
|
||||||
import emitter from '@ohos.events.emitter';
|
import emitter from '@ohos.events.emitter';
|
||||||
import { Constants } from './utils/Constants';
|
import { Constants } from './utils/Constants';
|
||||||
import taskpool from '@ohos.taskpool';
|
import taskpool from '@ohos.taskpool';
|
||||||
import { FileTypeUtil } from './utils/FileTypeUtil';
|
import { FileTypeUtil } from './utils/FileTypeUtil';
|
||||||
import util from '@ohos.util';
|
|
||||||
import { IEngineKey } from './key/IEngineKey';
|
import { IEngineKey } from './key/IEngineKey';
|
||||||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||||||
import {
|
import {
|
||||||
|
@ -38,8 +33,9 @@ import {
|
||||||
RequestJobResult,
|
RequestJobResult,
|
||||||
RequestJobRequest
|
RequestJobRequest
|
||||||
} from './model/ImageKnifeData'
|
} from './model/ImageKnifeData'
|
||||||
import { combineArrayBuffers } from './model/utils';
|
|
||||||
import { BusinessError } from '@kit.BasicServicesKit';
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import { ImageKnifeLoader } from './ImageKnifeLoader'
|
||||||
|
|
||||||
|
|
||||||
export class ImageKnifeDispatcher {
|
export class ImageKnifeDispatcher {
|
||||||
// 最大并发
|
// 最大并发
|
||||||
|
@ -52,7 +48,7 @@ export class ImageKnifeDispatcher {
|
||||||
private engineKey: IEngineKey = new DefaultEngineKey();
|
private engineKey: IEngineKey = new DefaultEngineKey();
|
||||||
|
|
||||||
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean {
|
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean {
|
||||||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc + "requestSource=" + requestSource + " isAnimator=" + isAnimator)
|
||||||
let memoryCache: ImageKnifeData | undefined;
|
let memoryCache: ImageKnifeData | undefined;
|
||||||
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||||||
memoryCache = {
|
memoryCache = {
|
||||||
|
@ -65,14 +61,12 @@ export class ImageKnifeDispatcher {
|
||||||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (memoryCache !== undefined) {
|
if (memoryCache !== undefined) {
|
||||||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:" + request.imageKnifeOption.loadSrc)
|
|
||||||
// 画主图
|
// 画主图
|
||||||
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
// 回调请求开始
|
// 回调请求开始
|
||||||
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||||||
request.imageKnifeOption.onLoadListener?.onLoadStart()
|
request.imageKnifeOption.onLoadListener.onLoadStart()
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
|
||||||
|
@ -83,22 +77,22 @@ export class ImageKnifeDispatcher {
|
||||||
request.requestState = ImageKnifeRequestState.COMPLETE
|
request.requestState = ImageKnifeRequestState.COMPLETE
|
||||||
// 回调请求开结束
|
// 回调请求开结束
|
||||||
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
||||||
request.imageKnifeOption.onLoadListener?.onLoadSuccess(memoryCache.source,memoryCache)
|
request.imageKnifeOption.onLoadListener.onLoadSuccess(memoryCache.source,memoryCache)
|
||||||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||||||
request.requestState = ImageKnifeRequestState.ERROR
|
request.requestState = ImageKnifeRequestState.ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_hasmemory:" + request.imageKnifeOption.loadSrc)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_false:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_nomemory:" + request.imageKnifeOption.loadSrc)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
||||||
|
|
||||||
//1.内存有的话直接渲染
|
//1.内存有的话直接渲染
|
||||||
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
||||||
return
|
return
|
||||||
|
@ -206,7 +200,7 @@ export class ImageKnifeDispatcher {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start:" + currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(subthread):" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
taskpool.execute(task).then((res: Object) => {
|
taskpool.execute(task).then((res: Object) => {
|
||||||
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||||||
if (isWatchProgress){
|
if (isWatchProgress){
|
||||||
|
@ -214,8 +208,9 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}).catch((err:BusinessError)=>{
|
}).catch((err: BusinessError) => {
|
||||||
LogUtil.error("Fail to execute in sub thread src=" + imageSrc + " err=" + err)
|
LogUtil.error("Fail to requestJob in sub thread src=" + imageSrc + " err=" + err)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
if (isWatchProgress){
|
if (isWatchProgress){
|
||||||
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
||||||
}
|
}
|
||||||
|
@ -223,12 +218,14 @@ export class ImageKnifeDispatcher {
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
})
|
})
|
||||||
} else { //主线程请求
|
} else { //主线程请求
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start(mainthread):" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
requestJob(request, requestList).then((res: RequestJobResult | undefined) => {
|
requestJob(request, requestList).then((res: RequestJobResult | undefined) => {
|
||||||
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}).catch((err:BusinessError)=>{
|
}).catch((err: BusinessError) => {
|
||||||
LogUtil.error("Fail to execute in main thread src=" + imageSrc + " err=" + err)
|
LogUtil.error("Fail to requestJob in main thread src=" + imageSrc + " err=" + err)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:" + currentRequest.imageKnifeOption.loadSrc)
|
||||||
this.executingJobMap.remove(memoryKey);
|
this.executingJobMap.remove(memoryKey);
|
||||||
this.dispatchNextJob();
|
this.dispatchNextJob();
|
||||||
})
|
})
|
||||||
|
@ -257,6 +254,7 @@ export class ImageKnifeDispatcher {
|
||||||
}
|
}
|
||||||
let pixelmap = requestJobResult.pixelMap;
|
let pixelmap = requestJobResult.pixelMap;
|
||||||
if (pixelmap === undefined) {
|
if (pixelmap === undefined) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.pixelmap undefined:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
// 回调请求失败
|
// 回调请求失败
|
||||||
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
||||||
|
@ -311,8 +309,6 @@ export class ImageKnifeDispatcher {
|
||||||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||||||
}
|
}
|
||||||
if (requestList !== undefined) {
|
if (requestList !== undefined) {
|
||||||
|
|
||||||
// todo 判断request生命周期,已销毁的不需要再绘制
|
|
||||||
// key相同的request,一起绘制
|
// key相同的request,一起绘制
|
||||||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
||||||
|
@ -360,11 +356,13 @@ export class ImageKnifeDispatcher {
|
||||||
while (true) {
|
while (true) {
|
||||||
let request = this.jobQueue.pop()
|
let request = this.jobQueue.pop()
|
||||||
if (request === undefined) {
|
if (request === undefined) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:no any job")
|
||||||
break // 队列已无任务
|
break // 队列已无任务
|
||||||
}
|
}
|
||||||
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start executeJob:" + request.imageKnifeOption.loadSrc)
|
||||||
this.executeJob(request)
|
this.executeJob(request)
|
||||||
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:" + request.imageKnifeOption.loadSrc)
|
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end executeJob:" + request.imageKnifeOption.loadSrc)
|
||||||
break
|
break
|
||||||
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||||||
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
||||||
|
@ -395,293 +393,44 @@ export class ImageKnifeDispatcher {
|
||||||
*/
|
*/
|
||||||
@Concurrent
|
@Concurrent
|
||||||
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> {
|
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> {
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src + " requestSource=" + request.requestSource)
|
||||||
let resBuf: ArrayBuffer | undefined
|
|
||||||
let bufferSize: number = 0
|
|
||||||
let loadError: string = '';
|
|
||||||
|
|
||||||
class RequestData {
|
|
||||||
receiveSize: number = 2000
|
|
||||||
totalSize: number = 2000
|
|
||||||
}
|
|
||||||
let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src
|
let src = typeof request.src == "number" ? request.resName != undefined ? request.resName : request.src + "" : request.src
|
||||||
// 生成文件key
|
// 生成文件缓存key
|
||||||
let fileKey = request.engineKey.generateFileKey(src, request.signature,request.isAnimator)
|
let fileKey = request.engineKey.generateFileKey(src, request.signature, request.isAnimator)
|
||||||
|
|
||||||
// 判断自定义下载
|
//获取图片资源
|
||||||
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") {
|
let resBuf: ArrayBuffer
|
||||||
// 先从文件缓存获取
|
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
|
||||||
if (resBuf === undefined) {
|
|
||||||
LogUtil.log("customGetImage customGetImage");
|
|
||||||
resBuf = await request.customGetImage(request.context, request.src)
|
|
||||||
loadError = resBuf == undefined ? "customGetImage loadFile" : loadError
|
|
||||||
// 保存文件缓存
|
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
|
||||||
let copyBuf = buffer.concat([buffer.from(resBuf)]).buffer; // IDE有bug,不能直接获取resBuf.byteLength
|
|
||||||
bufferSize = copyBuf.byteLength
|
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (typeof request.src === 'string') {
|
|
||||||
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
|
||||||
// 先从文件缓存获取
|
|
||||||
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
|
||||||
if (resBuf === undefined && request.onlyRetrieveFromCache != true) {
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.start:"+request.src)
|
|
||||||
let httpRequest = http.createHttp();
|
|
||||||
let progress: number = 0
|
|
||||||
let arrayBuffers = new Array<ArrayBuffer>()
|
|
||||||
const headerObj: Record<string, object> = {}
|
|
||||||
if (request.headers != undefined) {
|
|
||||||
request.headers.forEach((value) => {
|
|
||||||
headerObj[value.key] = value.value
|
|
||||||
})
|
|
||||||
} else if (request.allHeaders.size > 0) {
|
|
||||||
request.allHeaders.forEach((value, key) => {
|
|
||||||
headerObj[key] = value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
httpRequest.on("dataReceive", (data: ArrayBuffer) => {
|
|
||||||
arrayBuffers.push(data)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (request.isWatchProgress) {
|
|
||||||
httpRequest.on('dataReceiveProgress', (data: RequestData) => {
|
|
||||||
// 下载进度
|
|
||||||
if (data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number')) {
|
|
||||||
let percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100)
|
|
||||||
if (progress !== percent) {
|
|
||||||
progress = percent
|
|
||||||
if (requestList === undefined) {
|
|
||||||
// 子线程
|
|
||||||
emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { "value": progress } })
|
|
||||||
}else {
|
|
||||||
// 主线程请求
|
|
||||||
requestList!.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
|
||||||
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
|
||||||
requestWithSource.request.imageKnifeOption.progressListener(progress)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
let promise = httpRequest.requestInStream(request.src, {
|
|
||||||
header: headerObj,
|
|
||||||
method: http.RequestMethod.GET,
|
|
||||||
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
|
||||||
connectTimeout: 60000,
|
|
||||||
readTimeout: 0,
|
|
||||||
// usingProtocol:http.HttpProtocol.HTTP1_1
|
|
||||||
// header: new Header('application/json')
|
|
||||||
});
|
|
||||||
|
|
||||||
await promise.then((data: number) => {
|
|
||||||
if (data == 200 || data == 206 || data == 204) {
|
|
||||||
resBuf = combineArrayBuffers(arrayBuffers)
|
|
||||||
} else {
|
|
||||||
loadError = "HttpDownloadClient has error, http code =" + JSON.stringify(data)
|
|
||||||
}
|
|
||||||
}).catch((err: Error) => {
|
|
||||||
loadError = err.message;
|
|
||||||
LogUtil.error("requestInStream ERROR : err = " + JSON.stringify(err));
|
|
||||||
});
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_httpRequest.end:"+request.src)
|
|
||||||
// 保存文件缓存
|
|
||||||
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
|
|
||||||
let copyBuf = combineArrayBuffers(arrayBuffers); // IDE有bug,不能直接获取resBuf.byteLength
|
|
||||||
bufferSize = copyBuf.byteLength
|
|
||||||
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogUtil.log("success get image from filecache for key = " + fileKey);
|
|
||||||
loadError = "success get image from filecache for key = " + fileKey;
|
|
||||||
}
|
|
||||||
} else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) {
|
|
||||||
await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => {
|
|
||||||
await fs.stat(file.fd).then(async (stat) =>{
|
|
||||||
let buf = new ArrayBuffer(stat.size);
|
|
||||||
await fs.read(file.fd, buf).then((readLen) => {
|
|
||||||
resBuf = buf;
|
|
||||||
fs.close(file.fd);
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
loadError = 'LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
loadError = 'LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
}).catch((err:BusinessError) => {
|
|
||||||
loadError ='LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code;
|
|
||||||
})
|
|
||||||
} else { //从本地文件获取
|
|
||||||
try {
|
try {
|
||||||
let stat = fs.statSync(request.src);
|
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.start:" + request.src)
|
||||||
if (stat.size > 0) {
|
resBuf = await ImageKnifeLoader.getImageArrayBuffer(request, requestList, fileKey)
|
||||||
let file = fs.openSync(request.src, fs.OpenMode.READ_ONLY);
|
LogUtil.log("ImageKnife_DataTime_requestJob.getImageArrayBuffer.end:" + request.src)
|
||||||
resBuf = new ArrayBuffer(stat.size);
|
} catch (error) {
|
||||||
fs.readSync(file.fd, resBuf);
|
LogUtil.error("ImageKnife_DataTime_requestJob.end: getImageArrayBuffer error " + request.src + " err=" + error)
|
||||||
fs.closeSync(file);
|
return ImageKnifeLoader.makeEmptyResult(error)
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (typeof err == 'string') {
|
|
||||||
loadError = err;
|
|
||||||
} else {
|
|
||||||
loadError = err.message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (typeof request.src == "number") { //从资源文件获取
|
|
||||||
let manager = request.context.createModuleContext(request.moduleName).resourceManager
|
|
||||||
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
|
||||||
if(request.src == -1) {
|
|
||||||
let resName = request.resName as string
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
|
||||||
if(request.src == -1) {
|
|
||||||
let resName = request.resName as string
|
|
||||||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
|
||||||
} else {
|
|
||||||
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取图片类型
|
||||||
if (resBuf == undefined) {
|
let typeValue = new FileTypeUtil().getFileType(resBuf);
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end_undefined:"+request.src)
|
|
||||||
return {
|
|
||||||
pixelMap: undefined,
|
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: loadError,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.start:"+request.src)
|
|
||||||
let fileTypeUtil = new FileTypeUtil();
|
|
||||||
let typeValue = fileTypeUtil.getFileType(resBuf);
|
|
||||||
if(typeValue == null) {
|
if(typeValue == null) {
|
||||||
return {
|
LogUtil.log("ImageKnife_DataTime_requestJob.end: getFileType is null " + request.src)
|
||||||
pixelMap: undefined,
|
return ImageKnifeLoader.makeEmptyResult("request is not a valid image source")
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: "request is not a valid image source",
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let imageSource: image.ImageSource = image.createImageSource(resBuf);
|
|
||||||
let decodingOptions: image.DecodingOptions = {
|
|
||||||
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
|
|
||||||
}
|
|
||||||
if(request.isAnimator) {
|
|
||||||
if (typeValue === 'gif' || typeValue === 'webp') {
|
|
||||||
let pixelMapList: Array<PixelMap> = []
|
|
||||||
let delayList: Array<number> = []
|
|
||||||
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
|
|
||||||
//sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList()
|
|
||||||
await imageSource.getDelayTimeList().then(delayTimes => {
|
|
||||||
if (pixelList.length > 0) {
|
|
||||||
for (let i = 0; i < pixelList.length; i++) {
|
|
||||||
pixelMapList.push(pixelList[i]);
|
|
||||||
if (i < delayTimes.length) {
|
|
||||||
delayList.push(delayTimes[i]);
|
|
||||||
} else {
|
|
||||||
delayList.push(delayTimes[delayTimes.length - 1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imageSource.release();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
pixelMap: "",
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
type: typeValue,
|
|
||||||
pixelMapList,
|
|
||||||
delayList
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
pixelMap: undefined,
|
|
||||||
bufferSize: 0,
|
|
||||||
fileKey: '',
|
|
||||||
loadFail: "ImageKnifeAnimatorComponent组件仅支持动态图",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let resPixelmap: PixelMap | undefined = undefined
|
|
||||||
if (typeValue === 'gif' || typeValue === 'webp') {
|
|
||||||
let frameCount = await imageSource.getFrameCount()
|
|
||||||
if(frameCount == undefined || frameCount == 1) {
|
|
||||||
} else {
|
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
let base64Help = new util.Base64Helper()
|
|
||||||
|
|
||||||
let base64str = "data:image/" + typeValue + ";base64," + base64Help.encodeToStringSync(new Uint8Array(resBuf))
|
// 解析图片
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end_GIF:"+request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.start:" + request.src)
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end_GIF:"+request.src)
|
let result: RequestJobResult = await ImageKnifeLoader.parseImage(resBuf, typeValue, fileKey, request)
|
||||||
return {
|
LogUtil.log("ImageKnife_DataTime_requestJob.parseImage.end:" + request.src)
|
||||||
pixelMap: base64str,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
size:size,
|
|
||||||
type:typeValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else if(typeValue == "svg") {
|
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
let scale = size.height / size.width
|
|
||||||
let hValue = Math.round(request.componentHeight);
|
|
||||||
let wValue = Math.round(request.componentWidth);
|
|
||||||
let defaultSize: image.Size = {
|
|
||||||
height: vp2px(wValue) * scale,
|
|
||||||
width: vp2px(wValue)
|
|
||||||
};
|
|
||||||
let opts: image.DecodingOptions = {
|
|
||||||
editable: true,
|
|
||||||
desiredSize: defaultSize
|
|
||||||
};
|
|
||||||
await imageSource.createPixelMap(opts)
|
|
||||||
.then((pixelmap: PixelMap) => {
|
|
||||||
resPixelmap = pixelmap
|
|
||||||
imageSource.release()
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
pixelMap: resPixelmap,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
type:typeValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
await imageSource.createPixelMap(decodingOptions)
|
|
||||||
.then((pixelmap: PixelMap) => {
|
|
||||||
resPixelmap = pixelmap
|
|
||||||
imageSource.release()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 图形变化
|
// 图形变化
|
||||||
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined) {
|
if (request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined && result?.pixelMap !== undefined && typeof result.pixelMap !== 'string') {
|
||||||
resPixelmap = await request.transformation?.transform(request.context, resPixelmap!, request.componentWidth, request.componentHeight);
|
LogUtil.log("ImageKnife_DataTime_requestJob.transform.start:" + request.src)
|
||||||
|
result.pixelMap = await request.transformation?.transform(request.context, result.pixelMap, request.componentWidth, request.componentHeight);
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob.transform.end:" + request.src)
|
||||||
}
|
}
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end:"+request.src)
|
|
||||||
LogUtil.log("ImageKnife_DataTime_requestJob.end:"+request.src)
|
LogUtil.log("ImageKnife_DataTime_requestJob.end:" + request.src)
|
||||||
return {
|
return result
|
||||||
pixelMap: resPixelmap,
|
|
||||||
bufferSize: bufferSize,
|
|
||||||
fileKey: fileKey,
|
|
||||||
size:size,
|
|
||||||
type:typeValue
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
CacheStrategy,
|
||||||
|
ImageKnifeRequestSource,
|
||||||
|
ImageKnifeRequestWithSource, RequestJobRequest } from './model/ImageKnifeData';
|
||||||
|
import List from '@ohos.util.List'
|
||||||
|
import { FileCache } from './utils/FileCache';
|
||||||
|
import { LogUtil } from './utils/LogUtil';
|
||||||
|
import { Constants } from './utils/Constants';
|
||||||
|
import http from '@ohos.net.http';
|
||||||
|
import { combineArrayBuffers } from './model/utils';
|
||||||
|
import { BusinessError } from '@kit.BasicServicesKit';
|
||||||
|
import fs from '@ohos.file.fs';
|
||||||
|
import emitter from '@ohos.events.emitter';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
import { RequestJobResult } from './model/ImageKnifeData'
|
||||||
|
import util from '@ohos.util';
|
||||||
|
|
||||||
|
class RequestData {
|
||||||
|
receiveSize: number = 2000
|
||||||
|
totalSize: number = 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法,故抽取到另一个类
|
||||||
|
*/
|
||||||
|
export class ImageKnifeLoader {
|
||||||
|
static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
|
||||||
|
request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
if(request.isAnimator) {
|
||||||
|
return ImageKnifeLoader.parseForAnimatorComponent(resBuf ,typeValue ,fileKey, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeValue === 'gif' || typeValue === 'webp') {
|
||||||
|
return ImageKnifeLoader.parseAnimatorImage(resBuf ,typeValue ,fileKey , request)
|
||||||
|
} else if(typeValue == "svg") {
|
||||||
|
return ImageKnifeLoader.parseSvgImage(resBuf ,typeValue ,fileKey , request)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
static makeEmptyResult(error: string): RequestJobResult{
|
||||||
|
return {
|
||||||
|
pixelMap: undefined,
|
||||||
|
bufferSize: 0,
|
||||||
|
fileKey: '',
|
||||||
|
loadFail: error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async parseNormalImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, request: RequestJobRequest):Promise<RequestJobResult> {
|
||||||
|
let resPixelmap: PixelMap | undefined = undefined
|
||||||
|
let decodingOptions: image.DecodingOptions = {
|
||||||
|
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
|
||||||
|
}
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
await imageSource.createPixelMap(decodingOptions)
|
||||||
|
.then((pixelmap: PixelMap) => {
|
||||||
|
resPixelmap = pixelmap
|
||||||
|
imageSource.release()
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
pixelMap: resPixelmap,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
size:size,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async parseSvgImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
|
||||||
|
request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
let resPixelmap: PixelMap | undefined = undefined
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
let scale = size.height / size.width
|
||||||
|
let hValue = Math.round(request.componentHeight);
|
||||||
|
let wValue = Math.round(request.componentWidth);
|
||||||
|
let defaultSize: image.Size = {
|
||||||
|
height: vp2px(wValue) * scale,
|
||||||
|
width: vp2px(wValue)
|
||||||
|
};
|
||||||
|
let opts: image.DecodingOptions = {
|
||||||
|
editable: true,
|
||||||
|
desiredSize: defaultSize
|
||||||
|
};
|
||||||
|
await imageSource.createPixelMap(opts)
|
||||||
|
.then((pixelmap: PixelMap) => {
|
||||||
|
resPixelmap = pixelmap
|
||||||
|
imageSource.release()
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
pixelMap: resPixelmap,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static async parseAnimatorImage(resBuf: ArrayBuffer, typeValue: string,
|
||||||
|
fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf)
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
let frameCount = await imageSource.getFrameCount()
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
|
imageSource.release()
|
||||||
|
|
||||||
|
if(frameCount == undefined || frameCount == 1) {
|
||||||
|
} else {
|
||||||
|
let base64str = "data:image/" + typeValue + ";base64," + new util.Base64Helper().encodeToStringSync(new Uint8Array(resBuf))
|
||||||
|
return {
|
||||||
|
pixelMap: base64str,
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
size:size,
|
||||||
|
type:typeValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return ImageKnifeLoader.parseNormalImage(resBuf, typeValue, fileKey, request)
|
||||||
|
}
|
||||||
|
// 为AnimatorComponent解析动图
|
||||||
|
static async parseForAnimatorComponent(resBuf: ArrayBuffer, typeValue: string, fileKey: string,request: RequestJobRequest): Promise<RequestJobResult> {
|
||||||
|
if (typeValue === 'gif' || typeValue === 'webp') {
|
||||||
|
let imageSource: image.ImageSource = image.createImageSource(resBuf);
|
||||||
|
if (imageSource === undefined){
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
||||||
|
}
|
||||||
|
let decodingOptions: image.DecodingOptions = {
|
||||||
|
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
|
||||||
|
}
|
||||||
|
let pixelMapList: Array<PixelMap> = []
|
||||||
|
let delayList: Array<number> = []
|
||||||
|
await imageSource.createPixelMapList(decodingOptions).then(async (pixelList: Array<PixelMap>) => {
|
||||||
|
//sdk的api接口发生变更:从.getDelayTime() 变为.getDelayTimeList()
|
||||||
|
await imageSource.getDelayTimeList().then(delayTimes => {
|
||||||
|
if (pixelList.length > 0) {
|
||||||
|
for (let i = 0; i < pixelList.length; i++) {
|
||||||
|
pixelMapList.push(pixelList[i]);
|
||||||
|
if (i < delayTimes.length) {
|
||||||
|
delayList.push(delayTimes[i]);
|
||||||
|
} else {
|
||||||
|
delayList.push(delayTimes[delayTimes.length - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageSource.release();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).catch((error: BusinessError) => {
|
||||||
|
imageSource.release()
|
||||||
|
return ImageKnifeLoader.makeEmptyResult(JSON.stringify(error))
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
pixelMap: "",
|
||||||
|
bufferSize: resBuf.byteLength,
|
||||||
|
fileKey: fileKey,
|
||||||
|
type: typeValue,
|
||||||
|
pixelMapList,
|
||||||
|
delayList
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ImageKnifeLoader.makeEmptyResult("ImageKnifeAnimatorComponent组件仅支持动态图")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取图片资源
|
||||||
|
static async getImageArrayBuffer(request: RequestJobRequest, requestList: List<ImageKnifeRequestWithSource> | undefined,fileKey:string): Promise<ArrayBuffer> {
|
||||||
|
let resBuf: ArrayBuffer | undefined
|
||||||
|
|
||||||
|
// 判断自定义下载
|
||||||
|
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC && typeof request.src == "string") {
|
||||||
|
// 先从文件缓存获取
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
||||||
|
if (resBuf === undefined) {
|
||||||
|
LogUtil.log("start customGetImage src=" + request.src)
|
||||||
|
try {
|
||||||
|
resBuf = await request.customGetImage(request.context, request.src)
|
||||||
|
LogUtil.log("end customGetImage src=" + request.src)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error('customGetImage loadFile failed! err = ' + err)
|
||||||
|
}
|
||||||
|
if (resBuf === undefined) {
|
||||||
|
throw new Error('customGetImage loadFile failed!')
|
||||||
|
}
|
||||||
|
// 保存文件缓存
|
||||||
|
if (request.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:" + request.src)
|
||||||
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf, request.fileCacheFolder)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:" + request.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (typeof request.src === 'string') {
|
||||||
|
if (request.src.indexOf("http://") == 0 || request.src.indexOf("https://") == 0) { //从网络下载
|
||||||
|
// 先从文件缓存获取
|
||||||
|
resBuf = FileCache.getFileCacheByFile(request.context, fileKey , request.fileCacheFolder)
|
||||||
|
if (resBuf !== undefined){
|
||||||
|
LogUtil.log("success get image from filecache for key = " + fileKey + " src = " + request.src)
|
||||||
|
}
|
||||||
|
else if (request.onlyRetrieveFromCache != true) {
|
||||||
|
LogUtil.log("HttpDownloadClient.start:" + request.src)
|
||||||
|
let httpRequest = http.createHttp();
|
||||||
|
let progress: number = 0
|
||||||
|
let arrayBuffers = new Array<ArrayBuffer>()
|
||||||
|
const headerObj: Record<string, object> = {}
|
||||||
|
if (request.headers != undefined) {
|
||||||
|
request.headers.forEach((value) => {
|
||||||
|
headerObj[value.key] = value.value
|
||||||
|
})
|
||||||
|
} else if (request.allHeaders.size > 0) {
|
||||||
|
request.allHeaders.forEach((value, key) => {
|
||||||
|
headerObj[key] = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
httpRequest.on("dataReceive", (data: ArrayBuffer) => {
|
||||||
|
arrayBuffers.push(data)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (request.isWatchProgress) {
|
||||||
|
httpRequest.on('dataReceiveProgress', (data: RequestData) => {
|
||||||
|
// 下载进度
|
||||||
|
if (data != undefined && (typeof data.receiveSize == 'number') && (typeof data.totalSize == 'number')) {
|
||||||
|
let percent = Math.round(((data.receiveSize * 1.0) / (data.totalSize * 1.0)) * 100)
|
||||||
|
if (progress !== percent) {
|
||||||
|
progress = percent
|
||||||
|
if (requestList === undefined) {
|
||||||
|
// 子线程
|
||||||
|
emitter.emit(Constants.PROGRESS_EMITTER + request.memoryKey, { data: { "value": progress } })
|
||||||
|
}else {
|
||||||
|
// 主线程请求
|
||||||
|
requestList!.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||||||
|
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
||||||
|
requestWithSource.request.imageKnifeOption.progressListener(progress)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let promise = httpRequest.requestInStream(request.src, {
|
||||||
|
header: headerObj,
|
||||||
|
method: http.RequestMethod.GET,
|
||||||
|
expectDataType: http.HttpDataType.ARRAY_BUFFER,
|
||||||
|
connectTimeout: 60000,
|
||||||
|
readTimeout: 0,
|
||||||
|
// usingProtocol:http.HttpProtocol.HTTP1_1
|
||||||
|
// header: new Header('application/json')
|
||||||
|
});
|
||||||
|
|
||||||
|
await promise.then((data: number) => {
|
||||||
|
if (data == 200 || data == 206 || data == 204) {
|
||||||
|
resBuf = combineArrayBuffers(arrayBuffers)
|
||||||
|
} else {
|
||||||
|
throw new Error("HttpDownloadClient has error, http code =" + JSON.stringify(data))
|
||||||
|
}
|
||||||
|
}).catch((err: Error) => {
|
||||||
|
throw new Error("HttpDownloadClient download ERROR : err = " + JSON.stringify(err))
|
||||||
|
});
|
||||||
|
LogUtil.log("HttpDownloadClient.end:" + request.src)
|
||||||
|
// 保存文件缓存
|
||||||
|
if (resBuf !== undefined && request.writeCacheStrategy !== CacheStrategy.Memory) {
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.start:"+request.src)
|
||||||
|
FileCache.saveFileCacheOnlyFile(request.context, fileKey, resBuf , request.fileCacheFolder)
|
||||||
|
LogUtil.log("ImageKnife_DataTime_requestJob_saveFileCacheOnlyFile.end:"+request.src)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error('onlyRetrieveFromCache,do not fetch image src = ' + request.src)
|
||||||
|
}
|
||||||
|
} else if (request.src.startsWith('datashare://') || request.src.startsWith('file://')) {
|
||||||
|
await fs.open(request.src, fs.OpenMode.READ_ONLY).then(async (file) => {
|
||||||
|
await fs.stat(file.fd).then(async (stat) =>{
|
||||||
|
let buf = new ArrayBuffer(stat.size);
|
||||||
|
await fs.read(file.fd, buf).then((readLen) => {
|
||||||
|
resBuf = buf;
|
||||||
|
fs.closeSync(file.fd);
|
||||||
|
}).catch((err:BusinessError) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.read err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
}).catch((err:BusinessError) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.stat err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
}).catch((err:BusinessError) => {
|
||||||
|
throw new Error('LoadDataShareFileClient fs.open err happened uri=' + request.src + " err.msg=" + err?.message + " err.code=" + err?.code)
|
||||||
|
})
|
||||||
|
} else { //从本地文件获取
|
||||||
|
try {
|
||||||
|
let stat = fs.statSync(request.src);
|
||||||
|
if (stat.size > 0) {
|
||||||
|
let file = fs.openSync(request.src, fs.OpenMode.READ_ONLY);
|
||||||
|
resBuf = new ArrayBuffer(stat.size);
|
||||||
|
fs.readSync(file.fd, resBuf);
|
||||||
|
fs.closeSync(file);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typeof request.src == "number") { //从资源文件获取
|
||||||
|
let manager = request.context.createModuleContext(request.moduleName).resourceManager
|
||||||
|
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
|
if(request.src == -1) {
|
||||||
|
let resName = request.resName as string
|
||||||
|
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
||||||
|
} else {
|
||||||
|
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
||||||
|
}
|
||||||
|
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
||||||
|
if(request.src == -1) {
|
||||||
|
let resName = request.resName as string
|
||||||
|
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
||||||
|
} else {
|
||||||
|
resBuf = manager.getMediaContentSync(request.src).buffer as ArrayBuffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resBuf === undefined){
|
||||||
|
throw new Error('getImageArrayBuffer undefined')
|
||||||
|
}
|
||||||
|
return resBuf
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
import { SparkMD5 } from '../3rd_party/sparkmd5/spark-md5'
|
|
||||||
import util from '@ohos.util'
|
|
||||||
|
|
||||||
export class Tools {
|
|
||||||
private static keyCache: util.LRUCache<string,string> = new util.LRUCache(1024)
|
|
||||||
public static generateMemoryKey(key: string | PixelMap | Resource): string{
|
|
||||||
return typeof key == "string"? key : JSON.stringify(key)
|
|
||||||
}
|
|
||||||
// 生成唯一的key
|
|
||||||
public static generateKey(key: string | PixelMap | Resource): string{
|
|
||||||
let keyCache = typeof key == "string"? key : JSON.stringify(key)
|
|
||||||
let result = Tools.keyCache.get(keyCache)
|
|
||||||
if(result != undefined) {
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result = SparkMD5.hashBinary(keyCache)
|
|
||||||
Tools.keyCache.put(keyCache,result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue