HarmonyOS WPS Open SDK:关闭回传后把 fileUri 拷成业务 filePath
在 HarmonyOS 应用里接入 @wps/wps_sdk 后,打开文档只是链路的一半。用户关窗时,最新内容通常落在 WPS 进程沙箱,而不是构造 OpenFileRequest 时传入的那条路径。若业务要上传、归档或再次打开,必须开启关闭回传,在 WPSApi.sendRequest 的 Promise resolve 之后解析 Result.data,再把文件拷进本应用 filesDir。直接拿 fileUri 当持久路径,或继续用打开前的 sandboxPath,都会把旧文件当新结果。字段语义以官方对接文档为准。
一、filePath 出现在哪一层
推荐时序:RegisterAppRequest 成功 → 待编辑文件已在本应用沙箱 → OpenFileRequest 写入 wpsTransferType 与 enableEdit → sendRequest → 用户关窗 → Promise 返回 → 拷贝 → 得到业务 filePath。
| 层 | 对象 | 能否当业务路径 |
|---|---|---|
| 打开入参 | 本应用沙箱路径 | 只表示打开前快照 |
| 回传原始值 | Result.data.fileUri / transferFd | 否,位于 WPS 侧 |
| 业务路径 | 拷贝后的本应用路径或 file:// URI | 是 |
未设置 enableTransferFile 与 wpsTransferType 时,拉起成功即可 ResultCode.OK 且 data 为空。这是「已打开」,不是「已拿到新文件」。UI 不要在空 data 时提示保存成功。开了回传后 Promise 会等到关窗,界面应提示「请关闭文档后再返回」。
一次堆满水印、extraOptions 与回传时,ResultCode.ERROR 很难归因。联调先绿注册与只读打开,再开可编辑,最后才开回传与拷贝。
二、开启回传:优先 wpsTransferType
OpenFileRequest 上两组字段相关,后者优先:
| 参数 | 作用 |
|---|---|
enableTransferFile = true | 按 URI 回传 |
wpsTransferType | TransferType.URI 或 TransferType.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。打开按钮在注册完成前禁用。外部选择器文件先 copyFileSync 到 filesDir 再作为构造参数,避免权限不足落到笼统 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 模式关注 transferFd、transferFileName、transferFileSize;部分版本信息嵌在 parameters。从 fd 分块 readSync 写入本应用文件,累计字节与 transferFileSize 不一致则按失败处理,避免上传残缺文件。写完后 closeSync 本应用文件与回传 fd,否则泄漏。大文件放到 TaskPool,避免卡住 UI。
统一入口建议先判 FD(transferFd >= 0),再回退 URI,与官方 Demo 的 handleCallbackData / handleCallbackDataByFd 顺序一致。Facade 同时返回 result 与 localPath,页面不直接碰 WPS 路径。
result.code !== ResultCode.OK 时展示 msg,不要进入拷贝。OK 且无 data 表示仅打开成功。data 有值但拷贝失败,与「回传失败」分开提示,才能区分 WPS 侧与本应用文件系统。
五、联调清单
- 注册 OK(正式包包名再验)
- 沙箱只读打开(未开回传,确认
data可空) enableEdit = true+TransferType.URI,关窗后出现fileUri- 拷贝到
filesDir,用本应用路径再打开或算 hash - (可选)FD 路径:校验 size、关闭 fd
- 故意未注册调用一次,确认进 catch
| 现象 | 优先查 |
|---|---|
| 一直转圈 | 开了回传是否还在等关窗 |
| OK 且 data 空 | 是否未设 wpsTransferType |
| 上传仍是旧文件 | 是否仍用打开前路径 |
| 拷贝失败 | 目录是否创建、源 URI 是否可读 |
| 抛异常 | 是否未注册就 sendRequest |
| 1013 | key / 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
更多推荐



所有评论(0)