HarmonyOS 鸿蒙Next Web组件加载本地html,网络请求跨域问题
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 联系官网客服。
提工单后,华为建议把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能继续加强在安全性方面的研发,保护用户的隐私和数据安全。
问下您这边,使用的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时固定的数据吗?帮忙解答一下,急!在线等