前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >鸿蒙web加载本地网页资源异常

鸿蒙web加载本地网页资源异常

原创
作者头像
shouyiyiyiyi
修改2025-03-05 14:41:44
修改2025-03-05 14:41:44
7400
代码可运行
举报
运行总次数:0
代码可运行

我们在使用web组件中发现本地资源,例如图片/Css等资源会有加载不成功的情况,web组件提供了一种拦截机制,可以在加载资源的时候拦截,并替换为本地资源,并回传给web组件,具体实现如下

核心就两步:

第一步,替换本地资源路径,相当于做了标记;

第二步,拦截标记过的资源,读取本地资源后并返回;

下面的所有代码是基于鸿蒙NEXT Api 12

代码语言:javascript
代码运行次数:0
复制
@Component
struct WebPage {
  // 跳转过来 传递的地址
  urlPath: string = ""
  controller = new webview.WebviewController()
  schemeHandler: webview.WebSchemeHandler = new webview.WebSchemeHandler();
  responseWeb: WebResourceResponse = new WebResourceResponse();
  fileDir: string = ""

  loadData() {
    try {
      if (this.urlPath.includes("http") == false) {
        this.loadLocalUrl()
      } else {
        this.controller.loadUrl(this.urlPath)
      }

    } catch (e) {
      showShortCenterToast("加载失败")
    }
  }

/// 第一步,替换本地资源路径
  loadLocalUrl() {
    let parts = this.urlPath.split('/');
    // 如果数组长度大于 1,移除最后一个元素
    if (parts.length > 1) {
      parts.pop();
    }
    // 当前H5所在文件夹的绝对路径
    this.fileDir = parts.join('/')

    let html = fs.readTextSync(this.urlPath)
    // 要插入的指定字符串
    const insertString = "http://local";
    // 定义正则表达式
    const regex = /src="([^"]+\.(?:png|jpg|gif))"/gi;
    // 执行替换操作
    const imageHtml = html.replace(regex, (_, p1: string) => {
      let content = `src="${insertString}/${p1}"`;
      return content
    });

    // href定义正则表达式
    const cssRegex = /href="([^"]+\.(?:css|html))"/gi;
    const cssHtml = imageHtml.replace(cssRegex, (_, p1: string) => {
      let content = `href="${insertString}/${p1}"`;
      return content
    });
    this.controller.loadData(
      cssHtml,
      'text/html',
      'UTF-8'
    );
  }

  build() {
    Web({ src: this.urlPath, controller: this.controller })
      .width(FULL_WIDTH)
      .mixedMode(MixedMode.All)
      .layoutWeight(1)
      .onControllerAttached(() => {
        this.loadData()
      })
      .onLoadIntercept((event) => {
        let url = event.data.getRequestUrl()
        // 跳转拦截
        if (url.toLowerCase().startsWith('http://local') && url.toLowerCase().endsWith("html/")) {
          url = url.replace("http://local", "")
          url = url.toUpperCase()
          url = url.replace("HTML/", "html")

          const filePath = this.fileDir + "/" + url
          if (fs.accessSync(filePath)) {
            this.urlPath = filePath
            this.loadLocalUrl()
            return true
          }
        }
        return false
      })
      .onInterceptRequest((event) => {
/// 第二步,拦截对应的资源,读取本地资源后并返回
        let url = event.request.getRequestUrl()
        // 本地资源加载拦截
        if (url.startsWith('http://local')) {
          const promise: Promise<String> = new Promise((resolve: Function, reject: Function) => {
            url = url.replace("http://local", "")
            const filePath = this.fileDir + "/" + url
            if (fs.accessSync(filePath)) {
              if (url.toLowerCase().endsWith(".png") ||
              url.toLowerCase().endsWith(".jpg") ||
              url.toLowerCase().endsWith(".gif") ||
              url.toLowerCase().endsWith(".css")) {

                const fd = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
                // 获取文件的大小
                const stat = fs.statSync(fd.fd);
                const fileSize = stat.size;
                // 创建一个指定大小的 ArrayBuffer
                const buffer = new ArrayBuffer(fileSize);
                // 读取文件内容到 ArrayBuffer
                fs.readSync(fd.fd, buffer);
                this.responseWeb.setResponseData(buffer);
                if (url.toLowerCase().endsWith(".css")) {
                  this.responseWeb.setResponseMimeType('text/css');
                } else {
                  this.responseWeb.setResponseMimeType('image/*');
                }
              }
              this.responseWeb.setResponseCode(200);
              this.responseWeb.setReasonMessage('OK');
              resolve("success");
            } else {
              reject("failed")
            }
          })
          promise.then(() => {
            this.responseWeb.setResponseIsReady(true);
          })
          this.responseWeb.setResponseIsReady(false);
          return this.responseWeb;
        }
        return null

      })
      .width(FULL_WIDTH)
      .height(FULL_HEIGHT)
  }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档