鸿蒙webview开发中web内部网络请求访问资源跨域问题,客户端解决方案

鸿蒙webview开发中web内部网络请求访问资源跨域问题,客户端解决方案

项目场景:

在鸿蒙系统的h5混合开发过程中,我们使用web组件进行混合开发,后台并未对跨域问题进行处理,web组件内部发送网络请求出现访问资源跨域问题。


问题描述

访问资源跨域是浏览器在发送网络请求时经常遇到的问题,而鸿蒙的web组件也就相当于一个浏览器,因此在web组件内部发送,也会出现跨域问题,这种问题一般需要再后台解决,但是鸿蒙官方也有提供客户端解决跨域的方案,官网:解决Web组件本地资源跨域问题-管理Web组件的网络安全与隐私-ArkWeb(方舟Web)-应用框架 - 华为HarmonyOS开发者


原因分析:

为了提高安全性,ArkWeb内核不允许file协议或者resource协议访问URL上下文中来自跨域的请求。因此,在使用Web组件加载本地离线资源的时候,Web组件会拦截file协议和resource协议的跨域访问。可以通过方法二设置一个路径列表,再使用file协议访问该路径列表中的资源,允许跨域访问本地文件。当Web组件无法访问本地跨域资源时,开发者可以在DevTools控制台中看到类似以下报错信息:

官方解决方案描述:

在鸿蒙官网,提供了两种解决方案:

一、为了使Web组件能够成功访问跨域资源,开发者应采用http或https等协议,替代原先使用的file或resource协议进行加载。其中,替代的url域名为自定义构造的仅供个人或者组织使用的域名,以避免与互联网上实际存在的域名产生冲突。同时,开发者需利用Web组件的onInterceptRequest方法,对本地资源进行拦截和相应的替换。

二、

通过设置设置一个路径列表。当使用file协议访问该列表中的资源时,允许进行跨域访问本地文件。此外,一旦设置了路径列表,file协议将仅限于访问列表内的资源(此时,fileAccess的行为将会被此接口行为覆盖)。路径列表中的路径必须符合以下任一路径格式:

1.应用文件目录通过Context.filesDir获取,其子目录示例如下:/data/storage/el2/base/files/example/data/storage/el2/base/haps/entry/files/example

2.应用资源目录通过Context.resourceDir获取,其子目录示例如下:/data/storage/el1/bundle/entry/resource/resfile/data/storage/el1/bundle/entry/resource/resfile/example

当路径列表中的任一路径不满足上述条件时,系统将抛出异常码401,并判定路径列表设置失败。若设置的路径列表为空,file协议的可访问范围将遵循fileAccess的规则。

解决方案:

由于本人在开发过程中使用到了第二种解决方案, 在这里本人提供具体的操作步骤,以及指出本人踩过的坑点。

在web组件上本使用的是  resource:// 协议去访问资源,使用如下 X:

 Web({ src: 'resource://rawfile/dist/index.html#/xxxx', controller: this.webController })

然而setPathAllowingUniversalAccess 属性需要读取的是/data/storage/el1/bundle/entry/resource/resfile目录下的文件,使用Context.resourceDir获取到的路径为空

原来是在项目创建时并不会自动生成resfile文件,需要我们手动创建,在项目的src/main/resources下新建文件夹:resfile

将打包好的dist文件,也就是h5页面文件,放在resfile文件夹下面,通过以下方法读取文件   

web({ src:'resource://resfile/dist/index.html#/xxxxxxx', controller: this.webController })

 做好以上步骤之后,就来到了解决跨域最为关键的点:

设置setPathAllowingUniversalAccess,这里需要指定解除跨域的文件

 // 在设置好setPathAllowingUniversalAccess 之后,需要将src置空,使用loadUrl加载页面 Web({ src: "", controller: this.webController }) .onControllerAttached(() => { try { // 设置允许可以跨域访问的路径列表 this.webController.setPathAllowingUniversalAccess([ // 这里获取到resfile文件目录,后边拼上自己的h5文件 getContext().resourceDir + "/dist/index.html" ]) this.webController.loadUrl('原页面路径') } catch (error) { console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); } }) .javaScriptAccess(true) .fileAccess(true) .domStorageAccess(true)

 至此即成功使用官方的第二种方法去在客户端解决咱们在鸿蒙+h5的混合开发中的h5页面跨域问题了

Read more

安利一款超实用的前端可视化打印设计器:Vue Print Designer

安利一款超实用的前端可视化打印设计器:Vue Print Designer

做前端开发的朋友应该都懂,业务开发中遇到打印需求真的头大 —— 手写分页逻辑繁琐、不同框架适配麻烦、票据 / 快递单这类定制化打印场景不好实现,找个趁手的打印插件更是难上加难。最近发现了一款开源的可视化打印设计器Vue Print Designer,完美解决了这些痛点,不管是快速开发还是企业级定制化需求都能满足,今天就跟大家详细聊聊这款工具。 一、Vue Print Designer 是什么? Vue Print Designer 是一款面向业务表单、标签、票据、快递单等打印场景的可视化设计器,核心主打模板化、变量化设计,还提供了静默打印、云打印能力,同时支持 PDF / 图片 / Blob 等多种导出方式,完全能覆盖日常开发中的各类打印需求。 它不是简单的打印插件,而是一套完整的打印解决方案,从可视化设计模板,到参数配置、多端打印,再到定制化扩展,一站式搞定,而且项目还在持续更新,最新版本已经支持英寸、厘米作为单位,对国际化和精细化设计更友好了。 项目地址:https://gitee.com/

ClawdBot高清演示:Web UI中模型加载、对话历史、Token统计界面截图

ClawdBot高清演示:Web UI中模型加载、对话历史、Token统计界面截图 1. ClawdBot 是什么?一个真正属于你的本地AI助手 ClawdBot 不是一个云端调用的网页工具,也不是需要注册账号的SaaS服务。它是一个能完整运行在你自己的笔记本、台式机甚至树莓派上的个人AI助手——所有推理、记忆、上下文管理都在本地完成,你的对话不会上传到任何第三方服务器。 它的核心能力由 vLLM 提供支撑。vLLM 是当前最高效的开源大模型推理引擎之一,以极低的显存占用和极高的吞吐量著称。ClawdBot 把 vLLM 封装成轻量级网关服务,再通过 Web UI 暴露直观的操作界面。这意味着:你不需要写一行 Python 代码,也不用配置 CUDA 环境变量,就能直接和 Qwen3-4B-Instruct 这类高质量中文模型对话,还能实时看到它“想了多久”、“用了多少字”、“上下文有多长”。 这不是概念演示,而是开箱即用的生产力工具。它不追求参数规模的堆砌,而是专注把“

使用Docker安装Ollama及Open-WebUI完整教程

作者:吴业亮 博客:wuyeliang.blog.ZEEKLOG.net 一、Ollama 简介及工作原理 1. Ollama 简介及原理 * 简介:Ollama 是一款轻量级、开源的大语言模型(LLM)运行工具,旨在简化本地部署和运行大语言模型的流程。它支持 Llama 3、Mistral、Gemini 等主流开源模型,用户无需复杂配置即可在本地设备(CPU 或 GPU)上快速启动模型,适用于开发测试、本地智能应用搭建等场景。 * 工作原理: * 采用模型封装机制,将大语言模型的运行环境、依赖库及推理逻辑打包为标准化格式,实现模型的一键下载、启动和版本管理。 * 通过优化的推理引擎适配硬件架构,支持 CPU 基础运行和 GPU 加速(如 NVIDIA CUDA),减少资源占用并提升响应速度。 * 提供简洁的

前端GraphQL客户端:优雅地获取数据

前端GraphQL客户端:优雅地获取数据 毒舌时刻 前端GraphQL?这不是后端的事吗? "REST API就够了,为什么要用GraphQL"——结果前端需要多次请求,数据冗余, "GraphQL太复杂了,我学不会"——结果错过了更灵活的数据获取方式, "我直接用fetch请求GraphQL,多简单"——结果缺少缓存、错误处理等功能。 醒醒吧,GraphQL不是后端的专利,前端也需要专业的客户端工具! 为什么你需要这个? * 减少网络请求:一次请求获取所有需要的数据 * 数据精确:只获取需要的数据,避免冗余 * 类型安全:自动生成TypeScript类型 * 缓存优化:智能缓存,减少重复请求 * 开发效率:简化数据获取逻辑 反面教材 // 反面教材:直接使用fetch请求GraphQL async function fetchGraphQL(query, variables) { const response = await