在 HarmonyOS 应用里接入 @wps/wps_sdk 后,打开文档只是链路的一半。用户关窗时,最新内容通常落在 WPS 进程沙箱,而不是构造 OpenFileRequest 时传入的那条路径。若业务要上传、归档或再次打开,必须开启关闭回传,在 WPSApi.sendRequest 的 Promise resolve 之后解析 Result.data,再把文件拷进本应用 filesDir。直接拿 fileUri 当持久路径,或继续用打开前的 sandboxPath,都会把旧文件当新结果。字段语义以官方对接文档为准。

一、filePath 出现在哪一层

推荐时序:RegisterAppRequest 成功 → 待编辑文件已在本应用沙箱 → OpenFileRequest 写入 wpsTransferTypeenableEditsendRequest → 用户关窗 → Promise 返回 → 拷贝 → 得到业务 filePath

对象能否当业务路径
打开入参本应用沙箱路径只表示打开前快照
回传原始值Result.data.fileUri / transferFd否,位于 WPS 侧
业务路径拷贝后的本应用路径或 file:// URI

未设置 enableTransferFilewpsTransferType 时,拉起成功即可 ResultCode.OKdata 为空。这是「已打开」,不是「已拿到新文件」。UI 不要在空 data 时提示保存成功。开了回传后 Promise 会等到关窗,界面应提示「请关闭文档后再返回」。

一次堆满水印、extraOptions 与回传时,ResultCode.ERROR 很难归因。联调先绿注册与只读打开,再开可编辑,最后才开回传与拷贝。

二、开启回传:优先 wpsTransferType

OpenFileRequest 上两组字段相关,后者优先:

参数作用
enableTransferFile = true按 URI 回传
wpsTransferTypeTransferType.URITransferType.FD,覆盖上一字段

工程上只设 wpsTransferType,避免双开关语义重叠。enableEdit 与回传独立:可编辑场景通常同时打开;只读预览不必开回传。

import { common } from '@kit.AbilityKit';
import {
  WPSApi,
  RegisterAppRequest,
  OpenFileRequest,
  TransferType,
  ResultCode,
} from '@wps/wps_sdk';

async function openWithUriTransfer(
  ctx: common.UIAbilityContext,
  sandboxPath: string
) {
  await ensureRegistered(ctx);
  const req = new OpenFileRequest(ctx, sandboxPath);
  req.enableEdit = true;
  req.wpsTransferType = TransferType.URI;
  return WPSApi.sendRequest(req);
}

sendRequest 必须处理 then / catch。未完成注册会抛异常,不是 code !== OK。打开按钮在注册完成前禁用。外部选择器文件先 copyFileSyncfilesDir 再作为构造参数,避免权限不足落到笼统 ERROR。

三、URI:fileUri 必须拷贝

URI 模式下 result.data.fileUri 指向 WPS 沙箱临时文件。用 @ohos.file.fs 只读打开,再 copyFileSync 到例如 context.filesDir/wps_callback/<ts>/,最后可用 fileuri.getUriFromPath 转成业务 URI。拷贝前 mkdirSync;拷贝后关闭源 fd。目录按时间戳隔离,避免并发打开互相覆盖。

import fs from '@ohos.file.fs';
import fileuri from '@ohos.file.fileuri';

function copyWpsUriToApp(
  ctx: common.UIAbilityContext,
  wpsFileUri: string
): string {
  const src = fs.openSync(wpsFileUri, fs.OpenMode.READ_ONLY);
  const name = (src.path ?? wpsFileUri).split('/').pop() ?? 'edited.docx';
  const dir = `${ctx.filesDir}/wps_callback/${Date.now()}/`;
  if (!fs.accessSync(dir)) {
    fs.mkdirSync(dir, true);
  }
  const dest = dir + name;
  fs.copyFileSync(src.fd, dest);
  fs.closeSync(src);
  return fileuri.getUriFromPath(dest);
}

不要把 fileUri 写入数据库当长期路径。WPS 清理临时目录后该 URI 即失效。上传、二次打开只消费拷贝结果。若打开策略不允许落地,拷贝成功后可对 WPS 侧临时路径 unlink;清理失败不应挡住已经得到的本应用路径。

四、FD:读完必须 close

FD 模式关注 transferFdtransferFileNametransferFileSize;部分版本信息嵌在 parameters。从 fd 分块 readSync 写入本应用文件,累计字节与 transferFileSize 不一致则按失败处理,避免上传残缺文件。写完后 closeSync 本应用文件与回传 fd,否则泄漏。大文件放到 TaskPool,避免卡住 UI。

统一入口建议先判 FD(transferFd >= 0),再回退 URI,与官方 Demo 的 handleCallbackData / handleCallbackDataByFd 顺序一致。Facade 同时返回 resultlocalPath,页面不直接碰 WPS 路径。

result.code !== ResultCode.OK 时展示 msg,不要进入拷贝。OK 且无 data 表示仅打开成功。data 有值但拷贝失败,与「回传失败」分开提示,才能区分 WPS 侧与本应用文件系统。

五、联调清单

  1. 注册 OK(正式包包名再验)
  2. 沙箱只读打开(未开回传,确认 data 可空)
  3. enableEdit = true + TransferType.URI,关窗后出现 fileUri
  4. 拷贝到 filesDir,用本应用路径再打开或算 hash
  5. (可选)FD 路径:校验 size、关闭 fd
  6. 故意未注册调用一次,确认进 catch
现象优先查
一直转圈开了回传是否还在等关窗
OK 且 data 空是否未设 wpsTransferType
上传仍是旧文件是否仍用打开前路径
拷贝失败目录是否创建、源 URI 是否可读
抛异常是否未注册就 sendRequest
1013key / secret / 包名 / HAR

Code Review 看:是否绕开注册、是否把 fileUri 当持久路径、是否忽略 catch、是否外部路径直传、FD 是否 close。每步只改一类行为。

六、协作与复测

PR 勾选:回传类型、拷贝目录、Release 无 secret、正式包包名。产品口头「编辑完要能上传」时,落到:是否开回传、是否等关窗、是否拷贝后再上传。周五用正式包再跑:注册 → 只读 → 可编辑 + URI → 拷贝校验。

日志固定打:是否已注册、是否开回传、code/msg、是否得到 localPath、包名后缀。真机用例标题写清 URI 或 FD。并发打开时拷贝目录隔离。换 HAR 后 clean。

七、小结

鸿蒙上 WPS Open SDK 的关闭回传,目标不是「Promise 里出现字符串」,而是 把 WPS 沙箱文件变成本应用沙箱里的 filePath。开启用 wpsTransferType;等待语义随回传改变;URI 拷贝、FD 分块读取后都必须落到 filesDir。页面只消费 Facade 给出的本地路径。

把「未开回传则 data 空属正常」「fileUri 禁止入库」「必须处理 then/catch」写进联调页。坚持清单两周,把旧路径当新文件的误报通常会下降。字段以官方对接文档为准。接入评审把这三句话写进检查表,比事后补洞更省成本。拷贝目录约定写进 Onboarding,新人合入会稳很多。


基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。
官方对接文档:https://365.kdocs.cn/l/clQl5cek2NoT

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐