HarmonyOS 鸿蒙Next中关于WebView中controller.postUrl

HarmonyOS 鸿蒙Next中关于WebView中controller.postUrl 服务端收不到controller.postUrl(string,postData)请求的postData参数;一样的参数用安卓请求,服务端是能收到postData参数的

有人遇到过吗?有什么解决办法没有?

aboutToAppear(): void {
  //加密字符串
  this.req = 'gcO5Nrm/FH0BpGmGEfxGw1Wbpl/3xwigzPjOFnfJio30LCEVbhVTSX8HyOfodYRo3h2BbAliDtAvvXPAwVWvl/oLLhO6ob4bdvGi0bWilCylqdxj/O1ir7eM5BKEdqvWJAmUeKlxzdHALzuJc8iiBgYzZO9UA2jLoxRfCzsVLu3QFTT19u0p6tPGNFUzgZ1cOQ7z0IyWniIbgDN09PWejNz0tLufcmwSm8mM1HsOHD2H5z63zPByAajFn9otiNfpp5tIcqlT/ftg7L5i2FtQNYB4Tb/6y3Xv7y+fGHCN7OWXW4+BzGL+UmGsG5B6aQNYFV5HDBmdYdlYOr4fruIA7LhRHKpDCduS8ZHmHhikqvne8CFyNLD6b74X6L6eNVJ1zjZqB9WrscLkZvbRA+Xwk/9bbCUiOu7/aWi5K8lVXYQsrS46PDl0nhz5NOTWPLHphvyiAjdccRasoeKZotKTIB98R5RZEhVcp0K7YP0WSgayTp9Nuagk5EtPc/I3UfXkinfrN/TFEKY+VjXAIdihMq43D9FjywWE2HCfOLs+LejWXYufX6UKuhrcLTeHuJZWgTmKwcQVqY2R+9wwk6Ugrq7N89R9ilugngoulFA9uSiZn9PS3SsmsWCEwK/zvfyAc+ns1aj1vzZ67/JNthgo2tmnfSQTg5ZxFh+bDA4pKpz1Zps/J3s9/rf2sKAeAy38n20yqRanxkTI94+Ugz4waV4Fg2rwB2GmAqaj2WaVOg+WK3SHyoeP01nrqsIa3SaiH66yVIDQKV4kwodBal9NJEyyTy5dvODojfwk+uYp2KyE8HCbL3ktiulue1VhaHeohWcnfOBUF7H9djwTaKDxj8vWS+XhkxnxEoeX7dk8WuK3iRNctVhz/zTIFYVqfxJD'
  this.targetUrl = 'https://sdk.tjyouxi.com/31793201354940523'
}
try {
  let data2 =encodeURIComponent(this.req);
  console.info(`url:${this.targetUrl},data:${this.test(data2)}`)
  this.controller.postUrl(this.targetUrl, this.test(data2))
}catch (error){
  const err = error as Error
  console.info(`webview err:${err.message}`)
}
test(str: string): ArrayBuffer {
  let buf = new ArrayBuffer(str.length);
  let buff = new Uint8Array(buf);

  for (let i = 0; i < str.length; i++) {
    buff[i] = str.charCodeAt(i);
  }
  return buf;
}

更多关于HarmonyOS 鸿蒙Next中关于WebView中controller.postUrl的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

尊敬的开发者,您好,

使用postUrl接口时需要注意:

  1. 使用"POST"方法传递数据,该请求必须采用"application/x-www-form-urlencoded"编码。

  2. postData的形式,请提供key=value形式的数据,然后将该key=value形式的数据转换为ArrayBuffer,如下:

    "Name=test&Password=test"
    

您可以参考postUrl文档所提供的示例写法。

更多关于HarmonyOS 鸿蒙Next中关于WebView中controller.postUrl的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这里建议先检查两个点:

  1. postUrl 的第二个参数官方定义是 ArrayBuffer,不是普通 string。

  2. 官方文档说明,POST 数据需要使用 application/x-www-form-urlencoded 编码;如果 URL 不是网络 URL,ArkWeb 会按 loadUrl 加载,并忽略 postData。

也就是说,服务端如果按表单参数读取,客户端需要把数据先组织成类似 key=value&key2=value2 的格式,再转换为 ArrayBuffer 传入,而不是直接传 JSON 字符串或密文原文。服务端也要按 application/x-www-form-urlencoded 方式接收。

依据:WebviewController.postUrl 官方文档:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-webview-webviewcontroller#posturl11

HarmonyOS WebView postUrl 与 Android 行为差异

HarmonyOS 的 WebviewController.postUrl() 和 Android WebView 的行为并不完全一致。

你现在最大的问题其实是:

你传进去的 postData 不是标准的 application/x-www-form-urlencoded 格式。

HarmonyOS WebView 很可能不会像 Android 那样帮你兜底处理。

你现在实际传的是:

encodeURIComponent(this.req)

然后直接转 ArrayBuffer。

但服务端一般期望收到的是:

key=value

这种格式。

你现在少了参数名。

你现在发出去的实际上类似:

gcO5Nrm/FH0BpGmGEfx...

而不是:

data=gcO5Nrm%2FFH0BpGm...

所以很多后端框架会认为 POST Body 为空。

建议改成:

let postData = `data=${encodeURIComponent(this.req)}`;
this.controller.postUrl(
  this.targetUrl,
  postDataToArrayBuffer(postData)
);

然后:

function postDataToArrayBuffer(str: string): ArrayBuffer {
  return new TextEncoder().encode(str).buffer;
}

不要再用:

charCodeAt

那个方式对中文、特殊字符、UTF8 都可能有坑。

你现在这个:

buff[i] = str.charCodeAt(i);

本质是按 UTF-16 写的,不是标准 HTTP POST UTF-8 字节流。

HarmonyOS WebView 对 POST 数据格式要求比 Android 更严格。

另外还有几个 HarmonyOS WebView 的坑:

1. postUrl 只能发 form-urlencoded

不能直接发:

  • JSON
  • Base64 二进制
  • 自定义 Body

官方行为和 Android 一样,本质是:

application/x-www-form-urlencoded

格式。

所以如果后端要求:

{
  "data":"xxx"
}

postUrl() 基本不适合。

建议改:

fetch()

或者:

@ohos.net.http

请求后:

controller.loadData()

2. HarmonyOS WebView 可能不自动带 Content-Type

有些服务端会因为没有:

Content-Type: application/x-www-form-urlencoded

直接忽略 body。

Android WebView 有时会自动补。

HarmonyOS 不一定。

所以很多人最后改成:

httpRequest.request(...)

然后:

webview.loadData()

绕过 postUrl。

3. 超长 POST 数据可能被 HarmonyOS WebView 截断

你这个加密串太长了。

HarmonyOS NEXT 的 WebView 内核目前确实有人反馈:

  • 超长 body
  • base64 body
  • 二进制 body

会出现:

  • body 丢失
  • 服务端收不到
  • 自动变 GET

的问题。

尤其是:

postUrl(url, ArrayBuffer)

这里兼容性不如 Android。

所以你这个场景,我其实更建议:

最稳方案

别用:

controller.postUrl()

改:

http.createHttp()

先请求接口:

POST

拿到 HTML 后:

controller.loadData()

或者:

controller.loadUrl()

这是 HarmonyOS 里目前最稳定的做法。

你现在这个场景很像:

  • SDK鉴权
  • 游戏登录
  • 支付跳转

这种场景 HarmonyOS WebView 的 postUrl 确实坑比较多。

最后给你一个 HarmonyOS NEXT 可用版本:

import web_webview from '@ohos.web.webview';

let postData = `data=${encodeURIComponent(this.req)}`;

let buffer = new TextEncoder().encode(postData).buffer;

this.controller.postUrl(
  this.targetUrl,
  buffer
);

如果服务端还是收不到:

那基本就不是你代码问题了。

而是 HarmonyOS WebView 内核对 POST Body 的兼容问题。

直接换:

@ohos.net.http

是最终解。

是不是编码问题导致的;使用"POST"方法传递数据。 该请求必须采用"application/x-www-form-urlencoded"编码。检查下服务端是否有报错日志

在HarmonyOS Next中,WebviewControllerpostUrl(url: string, postData: ArrayBuffer): void用于向指定URL发送POST请求并加载响应。postData需转换为ArrayBuffer(如new ArrayBuffer())。需确保已获取webview组件并绑定控制器。

问题出在 postUrl 第二个参数需传入 ArrayBuffer,但服务端解析时需匹配 Content-Type。你的代码直接将整个经 encodeURIComponent 处理过的字符串转为 ArrayBuffer 整体发送,服务端若按 application/x-www-form-urlencoded 解析,无法识别为键值对格式,因此 postData 丢失。

修正:构造 key=value 格式的表格数据再转为 ArrayBuffer

let postData = 'data=' + encodeURIComponent(this.req); // 键值对格式
let buf = new ArrayBuffer(postData.length);
let buff = new Uint8Array(buf);
for (let i = 0; i < postData.length; i++) {
  buff[i] = postData.charCodeAt(i);
}
this.controller.postUrl(this.targetUrl, buf);

另外,若服务端要求 JSON 格式,直接将 JSON 字符串转为 ArrayBuffer 并设置请求头 Content-Type: application/json,但 postUrl 无法直接设头,可改用 loadUrl 配合请求拦截。此修复仅针对表格数据场景。

回到顶部