forked from floraachy/ImageKnife
675 lines
30 KiB
Plaintext
675 lines
30 KiB
Plaintext
/*
|
||
* 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 { ImageKnifeRequest, ImageKnifeRequestState } from './ImageKnifeRequest'
|
||
import { DefaultJobQueue } from './utils/DefaultJobQueue'
|
||
import { IJobQueue } from './utils/IJobQueue'
|
||
import List from '@ohos.util.List';
|
||
import LightWeightMap from '@ohos.util.LightWeightMap';
|
||
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 { ImageKnifeData, CacheStrategy } from './model/ImageKnifeData';
|
||
import http from '@ohos.net.http';
|
||
import image from '@ohos.multimedia.image';
|
||
import emitter from '@ohos.events.emitter';
|
||
import { Constants } from './utils/Constants';
|
||
import taskpool from '@ohos.taskpool';
|
||
import { FileTypeUtil } from './utils/FileTypeUtil';
|
||
import util from '@ohos.util';
|
||
import { IEngineKey } from './key/IEngineKey';
|
||
import { DefaultEngineKey } from './key/DefaultEngineKey';
|
||
import {
|
||
ImageKnifeRequestWithSource,
|
||
ImageKnifeRequestSource,
|
||
RequestJobResult,
|
||
RequestJobRequest
|
||
} from './model/ImageKnifeData'
|
||
import { combineArrayBuffers } from './model/utils';
|
||
import { BusinessError } from '@kit.BasicServicesKit';
|
||
|
||
export class ImageKnifeDispatcher {
|
||
// 最大并发
|
||
private maxRequests: number = 8
|
||
// 排队队列
|
||
private jobQueue: IJobQueue = new DefaultJobQueue()
|
||
// 执行中的请求
|
||
executingJobMap: LightWeightMap<string, List<ImageKnifeRequestWithSource>> = new LightWeightMap();
|
||
// 开发者可配置全局缓存
|
||
private engineKey: IEngineKey = new DefaultEngineKey();
|
||
|
||
showFromMemomry(request: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): boolean {
|
||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.start:" + request.imageKnifeOption.loadSrc)
|
||
let memoryCache: ImageKnifeData | undefined;
|
||
if ((typeof (request.imageKnifeOption.loadSrc as image.PixelMap).isEditable) == 'boolean') {
|
||
memoryCache = {
|
||
source: request.imageKnifeOption.loadSrc as image.PixelMap,
|
||
imageWidth: 0,
|
||
imageHeight: 0,
|
||
}
|
||
} else {
|
||
memoryCache = ImageKnife.getInstance()
|
||
.loadFromMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, request.imageKnifeOption,isAnimator));
|
||
}
|
||
|
||
|
||
if (memoryCache !== undefined) {
|
||
// 画主图
|
||
if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||
// 回调请求开始
|
||
if (requestSource === ImageKnifeRequestSource.SRC && request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||
request.imageKnifeOption.onLoadListener?.onLoadStart()
|
||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadStart:" + request.imageKnifeOption.loadSrc)
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.start:" + request.imageKnifeOption.loadSrc)
|
||
request.ImageKnifeRequestCallback?.showPixelMap(request.componentVersion, memoryCache.source, requestSource,memoryCache.imageAnimator)
|
||
LogUtil.log("ImageKnife_DataTime_MemoryCache_showPixelMap.end:" + request.imageKnifeOption.loadSrc)
|
||
|
||
if (requestSource == ImageKnifeRequestSource.SRC) {
|
||
request.requestState = ImageKnifeRequestState.COMPLETE
|
||
// 回调请求开结束
|
||
if (request.imageKnifeOption.onLoadListener?.onLoadSuccess !== undefined) {
|
||
request.imageKnifeOption.onLoadListener?.onLoadSuccess(memoryCache.source,memoryCache)
|
||
LogUtil.log("ImageKnife_DataTime_MemoryCache_onLoadSuccess:" + request.imageKnifeOption.loadSrc)
|
||
}
|
||
} else if (requestSource == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||
request.requestState = ImageKnifeRequestState.ERROR
|
||
}
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_true:" + request.imageKnifeOption.loadSrc)
|
||
return true
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_showFromMemomry.end_false:" + request.imageKnifeOption.loadSrc)
|
||
return false
|
||
}
|
||
|
||
|
||
enqueue(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
||
|
||
//1.内存有的话直接渲染
|
||
if (this.showFromMemomry(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)) {
|
||
return
|
||
}
|
||
// 2.内存获取占位图
|
||
if (request.imageKnifeOption.placeholderSrc !== undefined) {
|
||
if (this.showFromMemomry(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)) {
|
||
request.drawPlayHolderSuccess = true
|
||
}
|
||
}
|
||
//3.判断是否要排队
|
||
if (this.executingJobMap.length > this.maxRequests) {
|
||
this.jobQueue.add(request)
|
||
return
|
||
}
|
||
this.executeJob(request,isAnimator)
|
||
}
|
||
|
||
executeJob(request: ImageKnifeRequest,isAnimator?: boolean): void {
|
||
LogUtil.log("ImageKnife_DataTime_executeJob.start:" + request.imageKnifeOption.loadSrc)
|
||
// 加载占位符
|
||
if (request.imageKnifeOption.placeholderSrc !== undefined && request.drawPlayHolderSuccess == false) {
|
||
this.getAndShowImage(request, request.imageKnifeOption.placeholderSrc, ImageKnifeRequestSource.PLACE_HOLDER)
|
||
}
|
||
|
||
// 加载主图
|
||
this.getAndShowImage(request, request.imageKnifeOption.loadSrc, ImageKnifeRequestSource.SRC,isAnimator)
|
||
LogUtil.log("ImageKnife_DataTime_executeJob.end:" + request.imageKnifeOption.loadSrc)
|
||
}
|
||
|
||
/**
|
||
* 获取和显示图片
|
||
*/
|
||
getAndShowImage(currentRequest: ImageKnifeRequest, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean): void {
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.start:" + currentRequest.imageKnifeOption.loadSrc)
|
||
let memoryKey: string = this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator)
|
||
let requestList: List<ImageKnifeRequestWithSource> | undefined = this.executingJobMap.get(memoryKey)
|
||
if (requestList == undefined) {
|
||
requestList = new List()
|
||
requestList.add({ request: currentRequest, source: requestSource })
|
||
this.executingJobMap.set(memoryKey, requestList)
|
||
} else {
|
||
requestList.add({ request: currentRequest, source: requestSource })
|
||
return
|
||
}
|
||
|
||
let isWatchProgress : boolean = false
|
||
|
||
// 回调请求开始
|
||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||
if (requestWithSource.source === ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart !== undefined) {
|
||
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadStart()
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadStart:" + currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
||
isWatchProgress = true
|
||
}
|
||
});
|
||
|
||
let request: RequestJobRequest = {
|
||
context: currentRequest.context,
|
||
src: imageSrc,
|
||
headers: currentRequest.imageKnifeOption.headerOption,
|
||
allHeaders: currentRequest.headers,
|
||
componentWidth:currentRequest.componentWidth,
|
||
componentHeight:currentRequest.componentHeight,
|
||
customGetImage: currentRequest.imageKnifeOption.customGetImage,
|
||
onlyRetrieveFromCache: currentRequest.imageKnifeOption.onlyRetrieveFromCache,
|
||
transformation: currentRequest.imageKnifeOption.transformation,
|
||
writeCacheStrategy: ImageKnife.getInstance()
|
||
.isFileCacheInit() ? currentRequest.imageKnifeOption.writeCacheStrategy : CacheStrategy.Memory, // 未初始化文件缓存时,不写文件缓存
|
||
engineKey: this.engineKey,
|
||
signature: currentRequest.imageKnifeOption.signature,
|
||
requestSource: requestSource,
|
||
isWatchProgress: isWatchProgress,
|
||
memoryKey: memoryKey,
|
||
fileCacheFolder: ImageKnife.getInstance().getFileCache()?.getCacheFolder(),
|
||
isAnimator:isAnimator
|
||
}
|
||
|
||
if(request.customGetImage == undefined) {
|
||
request.customGetImage = ImageKnife.getInstance().getCustomGetImage()
|
||
}
|
||
if (ImageKnife.getInstance().isRequestInSubThread){
|
||
// 启动线程下载和解码主图
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.start:" + currentRequest.imageKnifeOption.loadSrc)
|
||
let task = new taskpool.Task(requestJob, request)
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_Task.end:" + currentRequest.imageKnifeOption.loadSrc)
|
||
if (isWatchProgress){
|
||
emitter.on(Constants.PROGRESS_EMITTER + memoryKey, (data) => {
|
||
this.progressCallBack(requestList! , data?.data?.value as number)
|
||
});
|
||
}
|
||
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.start:" + currentRequest.imageKnifeOption.loadSrc)
|
||
taskpool.execute(task).then((res: Object) => {
|
||
this.doTaskCallback(res as RequestJobResult | undefined, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||
if (isWatchProgress){
|
||
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}).catch((err:BusinessError)=>{
|
||
LogUtil.error("Fail to execute in sub thread src=" + imageSrc + " err=" + err)
|
||
if (isWatchProgress){
|
||
emitter.off(Constants.PROGRESS_EMITTER + memoryKey)
|
||
}
|
||
this.executingJobMap.remove(memoryKey);
|
||
this.dispatchNextJob();
|
||
})
|
||
} else { //主线程请求
|
||
requestJob(request, requestList).then((res: RequestJobResult | undefined) => {
|
||
this.doTaskCallback(res, requestList!, currentRequest, memoryKey, imageSrc, requestSource,isAnimator);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_execute.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}).catch((err:BusinessError)=>{
|
||
LogUtil.error("Fail to execute in main thread src=" + imageSrc + " err=" + err)
|
||
this.executingJobMap.remove(memoryKey);
|
||
this.dispatchNextJob();
|
||
})
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 回调下载进度
|
||
* @param requestList 请求列表
|
||
* @param data 进度
|
||
*/
|
||
private progressCallBack(requestList:List<ImageKnifeRequestWithSource>, data: number) {
|
||
for (let i = 0; i < requestList.length; i++) {
|
||
let requestWithSource:ImageKnifeRequestWithSource = requestList[i]
|
||
if (requestWithSource.request.imageKnifeOption.progressListener !== undefined && requestWithSource.source === ImageKnifeRequestSource.SRC) {
|
||
requestWithSource.request.imageKnifeOption.progressListener(data)
|
||
}
|
||
}
|
||
}
|
||
|
||
private doTaskCallback(requestJobResult: RequestJobResult | undefined, requestList: List<ImageKnifeRequestWithSource> ,
|
||
currentRequest: ImageKnifeRequest, memoryKey: string, imageSrc: string | PixelMap | Resource, requestSource: ImageKnifeRequestSource,isAnimator?: boolean):void {
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.start:"+currentRequest.imageKnifeOption.loadSrc)
|
||
if (requestJobResult === undefined){
|
||
return
|
||
}
|
||
let pixelmap = requestJobResult.pixelMap;
|
||
if (pixelmap === undefined) {
|
||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||
// 回调请求失败
|
||
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
||
requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadFailed !== undefined &&
|
||
requestJobResult.loadFail) {
|
||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadFailed(requestJobResult.loadFail);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadFailed:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
if (requestWithSource.source === ImageKnifeRequestSource.SRC &&
|
||
requestWithSource.request.imageKnifeOption.errorholderSrc !== undefined) {
|
||
|
||
if (this.showFromMemomry(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
||
ImageKnifeRequestSource.ERROR_HOLDER) === false) {
|
||
this.getAndShowImage(requestWithSource.request, requestWithSource.request.imageKnifeOption.errorholderSrc,
|
||
ImageKnifeRequestSource.ERROR_HOLDER);
|
||
}
|
||
}
|
||
});
|
||
this.executingJobMap.remove(memoryKey);
|
||
return;
|
||
}
|
||
// 保存文件缓存
|
||
if (requestJobResult.bufferSize > 0 && currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.Memory) {
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.start:"+currentRequest.imageKnifeOption.loadSrc)
|
||
ImageKnife.getInstance().saveWithoutWriteFile(requestJobResult.fileKey, requestJobResult.bufferSize);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveWithoutWriteFile.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
|
||
let ImageKnifeData: ImageKnifeData = {
|
||
source: pixelmap!,
|
||
imageWidth: requestJobResult.size == undefined ? 0 : requestJobResult.size.width,
|
||
imageHeight: requestJobResult.size == undefined ? 0 : requestJobResult.size.height,
|
||
type:requestJobResult.type
|
||
};
|
||
if(requestJobResult.pixelMapList != undefined) {
|
||
let imageAnimator: Array<ImageFrameInfo> = []
|
||
requestJobResult.pixelMapList.forEach((item,index)=>{
|
||
imageAnimator.push({
|
||
src:requestJobResult.pixelMapList![index],
|
||
duration:requestJobResult.delayList![index]
|
||
})
|
||
})
|
||
ImageKnifeData.imageAnimator = imageAnimator
|
||
}
|
||
// 保存内存缓存
|
||
if (currentRequest.imageKnifeOption.writeCacheStrategy !== CacheStrategy.File) {
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.start:"+currentRequest.imageKnifeOption.loadSrc)
|
||
ImageKnife.getInstance()
|
||
.saveMemoryCache(this.engineKey.generateMemoryKey(imageSrc, requestSource, currentRequest.imageKnifeOption,isAnimator),
|
||
ImageKnifeData);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_saveMemoryCache.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
if (requestList !== undefined) {
|
||
|
||
// todo 判断request生命周期,已销毁的不需要再绘制
|
||
// key相同的request,一起绘制
|
||
requestList.forEach((requestWithSource: ImageKnifeRequestWithSource) => {
|
||
if (requestWithSource.request.requestState !== ImageKnifeRequestState.DESTROY) {
|
||
// 画主图
|
||
if (requestWithSource.source === ImageKnifeRequestSource.SRC ||
|
||
requestWithSource.source === ImageKnifeRequestSource.ERROR_HOLDER
|
||
|| (requestWithSource.source === ImageKnifeRequestSource.PLACE_HOLDER &&
|
||
requestWithSource.request.requestState === ImageKnifeRequestState.PROGRESS)) {
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.start:"+currentRequest.imageKnifeOption.loadSrc)
|
||
requestWithSource.request.ImageKnifeRequestCallback.showPixelMap(requestWithSource.request.componentVersion,
|
||
ImageKnifeData.source, requestWithSource.source,ImageKnifeData.imageAnimator);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_showPixelMap.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
|
||
if (requestWithSource.source == ImageKnifeRequestSource.SRC) {
|
||
requestWithSource.request.requestState = ImageKnifeRequestState.COMPLETE;
|
||
if (requestWithSource.request.imageKnifeOption.onLoadListener &&
|
||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess) {
|
||
// 回调请求成功
|
||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadSuccess(ImageKnifeData.source,ImageKnifeData);
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_onLoadSuccess:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
} else if (requestWithSource.source == ImageKnifeRequestSource.ERROR_HOLDER) {
|
||
requestWithSource.request.requestState = ImageKnifeRequestState.ERROR;
|
||
}
|
||
} else {
|
||
if (requestWithSource.source == ImageKnifeRequestSource.SRC && requestWithSource.request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||
// 回调请求成功
|
||
requestWithSource.request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
||
}
|
||
}
|
||
});
|
||
|
||
this.executingJobMap.remove(memoryKey);
|
||
this.dispatchNextJob();
|
||
} else {
|
||
LogUtil.log("error: no requestlist need to draw for key = " + memoryKey);
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_getAndShowImage_CallBack.end:"+currentRequest.imageKnifeOption.loadSrc)
|
||
}
|
||
|
||
|
||
dispatchNextJob() {
|
||
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.start")
|
||
while (true) {
|
||
let request = this.jobQueue.pop()
|
||
if (request === undefined) {
|
||
break // 队列已无任务
|
||
}
|
||
else if (request.requestState === ImageKnifeRequestState.PROGRESS) {
|
||
this.executeJob(request)
|
||
LogUtil.log("ImageKnife_DataTime_dispatchNextJob.end:" + request.imageKnifeOption.loadSrc)
|
||
break
|
||
}else if (request.requestState == ImageKnifeRequestState.DESTROY && request.imageKnifeOption.onLoadListener?.onLoadCancel) {
|
||
request.imageKnifeOption.onLoadListener.onLoadCancel("component has destroyed")
|
||
}
|
||
}
|
||
}
|
||
|
||
setMaxRequests(concurrency: number): void {
|
||
if (concurrency > 0) {
|
||
this.maxRequests = concurrency
|
||
}
|
||
}
|
||
|
||
setEngineKeyImpl(impl: IEngineKey): void {
|
||
this.engineKey = impl;
|
||
}
|
||
|
||
getEngineKeyImpl(): IEngineKey {
|
||
return this.engineKey;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 通过taskpool 二级缓存,下载/读取本地文件,编解码
|
||
* @param context
|
||
* @param src
|
||
* @returns
|
||
*/
|
||
@Concurrent
|
||
async function requestJob(request: RequestJobRequest, requestList?: List<ImageKnifeRequestWithSource>): Promise<RequestJobResult | undefined> {
|
||
LogUtil.log("ImageKnife_DataTime_requestJob.start:" + request.src)
|
||
let resBuf: ArrayBuffer | undefined
|
||
let bufferSize: number = 0
|
||
let loadError: string = '';
|
||
|
||
class RequestData {
|
||
receiveSize: number = 2000
|
||
totalSize: number = 2000
|
||
}
|
||
|
||
// 生成文件key
|
||
let fileKey = request.engineKey.generateFileKey(request.src, request.signature,request.isAnimator)
|
||
|
||
// 判断自定义下载
|
||
if (request.customGetImage !== undefined && request.requestSource == ImageKnifeRequestSource.SRC) {
|
||
// 先从文件缓存获取
|
||
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: 6000,
|
||
readTimeout: 6000,
|
||
// 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 {
|
||
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) {
|
||
if (typeof err == 'string') {
|
||
loadError = err;
|
||
} else {
|
||
loadError = err.message;
|
||
}
|
||
}
|
||
}
|
||
} else if ((request.src as Resource).id !== undefined) { //从资源文件获取
|
||
let res = request.src as Resource;
|
||
let manager = request.context.createModuleContext(res.moduleName).resourceManager
|
||
if (resBuf == undefined && request.onlyRetrieveFromCache != true && request.requestSource == ImageKnifeRequestSource.SRC) {
|
||
if(res.id == -1) {
|
||
let resName = (res.params![0] as string)
|
||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
||
} else {
|
||
resBuf = manager.getMediaContentSync(res.id).buffer as ArrayBuffer
|
||
}
|
||
} else if (resBuf == undefined && request.requestSource != ImageKnifeRequestSource.SRC) {
|
||
if(res.id == -1) {
|
||
let resName = (res.params![0] as string)
|
||
resBuf = (await manager.getMediaByName(resName.substring(10))).buffer as ArrayBuffer
|
||
} else {
|
||
resBuf = manager.getMediaContentSync(res.id).buffer as ArrayBuffer
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
if (resBuf == undefined) {
|
||
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) {
|
||
return {
|
||
pixelMap: undefined,
|
||
bufferSize: 0,
|
||
fileKey: '',
|
||
loadFail: "request is not a valid image source",
|
||
}
|
||
}
|
||
let imageSource: image.ImageSource = image.createImageSource(resBuf);
|
||
let decodingOptions: image.DecodingOptions = {
|
||
editable: true,
|
||
}
|
||
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 delayList = await imageSource.getDelayTimeList()
|
||
if(delayList == undefined) {
|
||
} 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.end_GIF:"+request.src)
|
||
return {
|
||
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) {
|
||
resPixelmap = await request.transformation?.transform(request.context, resPixelmap!, request.componentWidth, request.componentHeight);
|
||
}
|
||
LogUtil.log("ImageKnife_DataTime_requestJob_createPixelMap.end:"+request.src)
|
||
LogUtil.log("ImageKnife_DataTime_requestJob.end:"+request.src)
|
||
return {
|
||
pixelMap: resPixelmap,
|
||
bufferSize: bufferSize,
|
||
fileKey: fileKey,
|
||
size:size,
|
||
type:typeValue
|
||
};
|
||
}
|
||
|