Web组件加载沙箱HTML页面实践
鸿蒙提供了丰富的各种视图组件,同时还支持加载沙箱目录下的HTML页面并显示。我的需求是从一个网络资源地址下载一个zip压缩包到files沙箱目录下,然后解压缩到指定文件夹,最后在一个Entry页面里用Web组件加载解压出来的HTML页面并显示。需求不难,第一步下载zip压缩文件:
const downloadTask = await request.downloadFile(AppContextInstance.context, {
url: downloadUrl,
filePath: targetPath
})在解开压缩文件之前,为了保险起见我写了一个方法检查目标解压目录是否存在,如果不存在则创建目录。示例代码如下:
// 确保目标目录存在,如果不存在则创建
public async ensureDirExists(dir: string): Promise<void> {
try {
fileIo.accessSync(dir);
} catch (error) {
try {
fileIo.mkdirSync(dir, true);
} catch (err2) {
console.log(err2)
}
}
}然后就是解开压缩文件了,这一步代码比较简单,示例如下:
zlib.decompressFile(zipFileAbsPath, unzipDirAbsPath)
解开压缩文件之后,就是通过router跳转到加载HTML的Entry Page,示例代码如下:
router.pushUrl({
url: 'web_view/WebPage',
params: {
'openUrl': 'file://' + this.absPath(fileName, fileRelativePath)
}
})为了可以灵活加载不同的HTML文件,我通过传递params的方式将目标沙箱HTML文件的路径以openUrl的参数名传递过去,Entry Page页面示例代码如下:
import { webview } from '@kit.ArkWeb'
import { router } from '@kit.ArkUI'
@Entry
@Component
struct WebPage {
openUrl: string = ''
webCtl: webview.WebviewController = new webview.WebviewController()
aboutToAppear(): void {
const paramsObj = router.getParams() as Record<string, boolean | number | string>
if (paramsObj) {
this.openUrl = paramsObj['openUrl'] as string
}
}
build() {
Column() {
Text(this.openUrl)
Web({
src: this.openUrl,
controller: this.webCtl
})
.domStorageAccess(true)
.width('100%')
.height('80%')
.showBorderEdge()
}.width('100%')
.height('100%')
}
}然而当一切准备就绪,在真机上测试的时候却发现HTML页面始终没有加载出来,进入沙箱目录检查发现是创建解压文件夹那一步出错了,虽然文件夹还没有创建,但是fileIo.accessSync(dir)这行代码并没有抛出异常,也就导致fileIo.mkdirSync(dir, true)这行代码没有执行,进而解压文件也没有放入指定目录,自然Web组件就无法加载一个不存在的路径的HTML页面了。于是就粗暴地将第二步改为直接创建文件夹了,示例代码如下:
// 确保目标目录存在,如果不存在则创建
public async createDir(dir: string): Promise<void> {
try {
fileIo.mkdirSync(dir, true);
} catch (err2) {
console.log(err2)
}
}改了之后,就顺利地完成了下载zip压缩文件,然后解压到指定文件夹,最后跳转到Entry Page成功地加载并显示出了本地沙箱HTML页面。略有遗憾的是下载zip压缩文件里的图片资源含有中文命名,zlib解压中文文件名出来是乱码,导致Web加载HTML页面也无法正常显示部分图片。