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页面也无法正常显示部分图片。