在 HarmonyOS 应用里用 WPS Open SDK 打开 Office 文档,产品验收很少停在「能编辑」。更常见的是:文档能不能在 WPS 客户端侧留下副本、用户能不能分享或打印、关窗后业务侧能不能拿到结果且不留 WPS 临时文件。对接文档把「不落地」定义成:WPS 打开后不在 WPS 侧持久化缓存副本,并限制云同步、另存为、打印等外泄能力。开关落在 OpenFileRequest.enableLocalization 上。本文按工程视角梳理生效条件、强制关闭清单、与 extraOptions 的优先级,以及 URI 回传后的清理写法。示例基于 TypeScript 封装改写,便于在同一仓库里复用到预览、编辑、回传多条业务线。
为什么需要单独理解 enableLocalization
很多团队先把 registerApp、enableEdit 跑绿,再叠水印或 extraOptions,最后才发现:分享按钮关不掉、打印入口仍在、extraOptions.enablePrint = false 像没写一样。根因往往是不落地默认生效——在支持该能力的 HAR 上,未设置或 false 即不落地,SDK 会强制关闭一批能力,覆盖你在 extraOptions 里的赋值。
调用链固定为:
registerApp(OK) → setWpsFileToken? → 沙箱路径 → OpenFileRequest → enableEdit → enableLocalization → 水印/修订/extraOptions/transfer → sendRequest
策略层字段不要和注册、路径混写在一个巨型回调里;联调顺序建议:注册 → 可编辑打开 → 确认不落地默认 → 再叠水印或回传。
字段语义与 SdkConstants 分支
enableLocalization | 支持能力的包体上 | 敏感菜单 |
|---|---|---|
未设置 / false | 不落地(默认) | 强制关闭 |
true | 允许落地 | 可由 extraOptions 细配 |
当 SdkConstants.isPersonalSdk() 返回 false 时,字段在对应 HAR 上生效;返回 true 时,赋值不会生效,不落地逻辑不会被触发。同一套 TypeScript 代码可以复用,但行为取决于集成的 HAR 包体——适配层用 SdkConstants.isPersonalSdk() 分支,页面层只传 allowLand 布尔。
import { common } from '@kit.AbilityKit';
import {
WPSApi,
OpenFileRequest,
ResultCode,
SdkConstants,
} from '@wps/wps_sdk';
export function buildOpenRequest(
ctx: common.UIAbilityContext,
path: string,
editable: boolean,
allowLand: boolean
): OpenFileRequest {
const req = new OpenFileRequest(ctx, path);
req.enableEdit = editable;
if (!SdkConstants.isPersonalSdk()) {
req.enableLocalization = allowLand;
}
return req;
}
合规默认保持不落地;只有产品明确需要 WPS 侧缓存时,才设 true 并同步设计 extraOptions 矩阵。
不落地时强制关闭的能力
下列能力在不落地模式下被 SDK 强制关闭,即使 extraOptions 打开也无效:
- 云文档 / 登录 / 收藏
- 分享、历史版本
- 另存为、打印、导出 PDF
- 复制、粘贴、剪切
- 文档截图
- 自动上传、图片存相册、解压到手机、外部应用打开
联调时若同事反馈「extraOptions 没生效」,先打印当前 enableLocalization 与 SdkConstants.isPersonalSdk(),再查菜单,比反复改布尔值省时间。
可落地后,上述能力不再被 SDK 一刀切;此时 OpenFileExtraOptions 仅对显式赋值的字段生效,适合「允许缓存但关分享」类产品策略。
注册、Token 与完整打开封装
import { WPSApi, Result, ResultCode, SdkConstants } from '@wps/wps_sdk';
let sdkReady = false;
export function bootstrapWps(
appKey: string,
appSecret: string,
activationSn?: string
): Promise<void> {
return new Promise((resolve, reject) => {
WPSApi.registerApp(appKey, appSecret, {
onCallback: (r: Result) => {
if (r.code === ResultCode.ERROR_CODE_AUTH_FAILURE) {
reject(new Error(`1013 ${r.msg}`));
return;
}
if (r.code !== ResultCode.OK) {
reject(new Error(`register ${r.code}`));
return;
}
if (!SdkConstants.isPersonalSdk() && activationSn) {
WPSApi.setWpsFileToken(activationSn);
}
sdkReady = true;
resolve();
},
});
});
}
export async function openWithLandingPolicy(
ctx: common.UIAbilityContext,
sandboxPath: string,
allowLand: boolean
): Promise<void> {
if (!sdkReady) {
throw new Error('WPS not ready');
}
const req = buildOpenRequest(ctx, sandboxPath, true, allowLand);
await WPSApi.sendRequest(req);
}
外部选择器 URI 应先 copyFileSync 到 filesDir,再构造 Request。未注册就打开会抛异常,此时改 enableLocalization 无意义。
URI 回传与 unlink 临时文件
开启关窗回传后,用户关闭 WPS 页,Result.data 可能带 WPS 沙箱内的临时 URI。业务侧拷贝到本应用沙箱再上传。不落地 + 回传时,拷贝成功后建议 fs.unlink 删除 WPS 临时文件;失败只记日志。
import fs from '@ohos.file.fs';
import { SdkConstants } from '@wps/wps_sdk';
export function finalizeTransfer(wpsUri: string, appDest: string): void {
fs.copyFileSync(wpsUri, appDest);
if (!SdkConstants.isPersonalSdk()) {
try {
fs.unlinkSync(wpsUri);
} catch (err) {
console.warn('[WPS] unlink', err);
}
}
}
未开回传时 OK + data=null 只表示拉起成功。UI 避免写成「保存成功」 unless 拷贝已完成。
联调清单与工程建议
| 步骤 | 动作 |
|---|---|
| 1 | 注册 +(按需)Token,确认 ready |
| 2 | 沙箱路径可编辑打开 |
| 3 | 默认不落地下,验分享/打印不可用 |
| 4 | allowLand=true 后,验 extraOptions 单项生效 |
| 5 | 回传:拷贝 + unlink |
| 6 | 正式包包名复测 1013 |
| 现象 | 查什么 |
|---|---|
| 菜单关不掉 | 是否仍不落地 |
| 字段无效果 | 形态判定是否为 true |
| 泛化 ERROR | 沙箱路径、注册状态 |
日志固定前缀 [WPS][land],输出 allowLand、形态判定、transfer 是否开启、code/msg。Release 不打 secret。把 enableLocalization 与 extraOptions 写进同一策略类型,Review 时问:默认是否仍不落地?不落地时是否误指望 extraOptions?回传是否 copy 后再 unlink?全仓 new OpenFileRequest 应收拢一处。Ability 冷启动完成注册,文档页只检查 ready。并发打开时沙箱子目录按时间戳隔离。
小结
enableLocalization 是文档安全策略的开关:默认不落地时 SDK 强制收敛外泄面;允许落地后才用 extraOptions 精细控制。形态差异用 SdkConstants.isPersonalSdk() 收在适配层,回传层记得拷贝后 unlink。字段以官方对接文档为准。坚持分层联调——先可编辑打开,再确认不落地,最后才开回传——比一次堆满合规开关更省排障时间。并发打开时沙箱子目录按时间戳隔离;产品改「预览也要关分享」时扩展 Facade 默认 allowLand=false 即可,不要 fork 第二套 open 函数。模块注释写明「不落地时部分 extraOptions 会被强制关闭」,可显著减少测试误报 SDK 故障。换 HAR 后 clean 重装,用正式包包名复测注册与不落地各一次;Release 日志只打布尔与 code,不打完整 appSecret。
基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。 官方对接文档:365.kdocs.cn/l/clQl5cek2… 技术交流 QQ 群:628436767