HarmonyOS 鸿蒙Next Web组件加载本地html,网络请求跨域问题

发布于 1周前 作者 h691938207 来自 鸿蒙OS

HarmonyOS 鸿蒙Next Web组件加载本地html,网络请求跨域问题

场景:将远程的HTML全部下载到SD卡中,使用加载本地html的方式打开页面。

页面打开后,使用chrome://inspect调试发现请求失败,报错如下

ccess to XMLHttpRequest at ‘https://xxx.com/xxx.json?rand=1711331799746’ from origin ‘null’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

现在想到的解决方案有四种:

1、拦截onInterceptRequest,在Header中添加 “Access-Control-Allow-Origin”: “"。代码如下,实际上无法修改header

.onInterceptRequest((event) => {
  if(event && event!!.request) {

    let head1:Header = {

      headerKey:“Access-Control-Allow-Origin”,

      headerValue:"

    }

  }

})

2、Web组件是否有设置允许跨域的API,类似Android中的 mixedContentMode

目前没看到类似的API

3、看到有个scheme处理跨域的方案:web_webview.WebCustomScheme

看了文档,尝试了多种写法,也没有效果

scheme13: web_webview.WebCustomScheme = {schemeName: “https”, isSupportCORS: true, isSupportFetch: true}

4、代理网络请求

onInterceptRequest中拦截Http请求,然后原生代理。目前不考虑该方案,优先使用简单的方式



关于HarmonyOS 鸿蒙Next Web组件加载本地html,网络请求跨域问题的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

9 回复

提工单后,华为建议把file域替换成自己的域名,然后在onInterceptRequest中拦截自己替换过的域名,去加载对应的html、js、css文件即可,由于不存在file域,就不存在跨域的问题。

但是遇到另一个问题,由于response的类型限制,只能接收string、number、Resource,如果资源是个图片,就无法使用。

官方给了我个方法:

可以使用web组件的loadData接口,用于加载指定的数据,该接口的参数baseUrl可以实现:入参baseUrl可以指定的一个URL路径(“http”/“https”/"data"协议),并由Web组件赋值给window.origin。通过该接口更改协议可以解决跨域问题。

不过我还没尝试,这个方法的文档看的不是很懂,后面有空再试试。

注意,读取文件的时候还有个坑,使用fs的readText方法,读出来的内容是错误的!!!无故添加多余的文本进来

最后通过读取byte的方式,最后将byte array 转成string才能用。

希望HarmonyOS能继续加强在安全性方面的研发,保护用户的隐私和数据安全。

更下下进度,图片等其他类型的资源问题也解决了。 这里不用读取string的方式返回资源,而是利用setResponseData有个number类型的参数,这个number对应的应该是File的fd属性。没看到相关文档,但是亲测可用。

步骤1:直接通过fs.openSync得到File对象 步骤2:为response赋值fd,resp.setResponseData(file.fd)

这样即可拦截并返回所有类型的资源文件。

注意!!! 这里如果使用异步的方式读取文件(fs.open),又较大概率出现资源无法加载的情况,怀疑的官方的bug

问下您这边,使用的loadData接口,是要读取index.html以string方式传入? 不知道您这边有没有遇到这样一种场景:加载的index.html的URL还携带了参数,例如:xxx/index.html#/h5-login/retail或者xxx/index.html?clientType=Android 以loadData加载的话,锚点参数和query参数就无法加载了。

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

我再拦截资源的时候也遇到类似的问题 我的本地资源是index.html,页面重新加载后,在后面加了#,如:#/h5-login 由于本地资源不会用到带#的路径,遇到这种情况,我在加载前把#后面的内容全部移除了

你如果是本地的应该不会使用到#或者其他参数,感觉你的情况跟我不大一样

通常是通过拦截并自定义请求头的形式。

Web({ src: 'www.example.com', controller: this.controller })
        .onInterceptRequest((event) => {
          if (event) {
            console.log('url:' + event.request.getRequestUrl())
          }
          let head1: Header = {
            headerKey: "Access-Control-Allow-Origin",
            headerValue: "*"
          }
          let head2: Header = {
            headerKey: "Cache-Control",
            headerValue: "no-cache"
          }
          let length = this.heads.push(head1)
          length = this.heads.push(head2)
          this.responseweb.setResponseHeader(this.heads)
          this.responseweb.setResponseData(this.webdata)
          this.responseweb.setResponseEncoding('utf-8')
          this.responseweb.setResponseMimeType('text/html')
          this.responseweb.setResponseCode(200)
          this.responseweb.setReasonMessage('OK')
          return this.responseweb
        })<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

webdata 是返回的页面数据。

若觉得用string的形式返回webdata的形式维护麻烦,可在拦截的过程中使用http请求,把请求的返回数据复制给webdata 同样能达到效果。

您这里的webdata时固定的数据吗?正常网络请求,这个数据应该都是从接口拿到的吧? 而且有另一个问题,这种形式代理get请求可以,但是遇到post请求的时候body拿不到,会少参数

您这里的webdata时固定的数据吗?帮忙解答一下,急!在线等

回到顶部