HarmonyOS WPS Open SDK:关闭回传 URI-FD 与沙箱 filePath

在 HarmonyOS 应用接入 @wps/wps_sdk 后,打开与编辑往往先跑通,下一步产品会要求「用户关文档后,把编辑结果拿回本应用」。对接文档把这类能力挂在 OpenFileRequest 的关闭回传参数上:enableTransferFilewpsTransferTypeTransferType.URI / TransferType.FD)。本文按调用链说明等待语义、结果字段、拷贝到本应用沙箱的写法与联调清单,细节以官方对接文档为准。

一、回传在打开链路中的位置

典型时序:registerApp 成功 → 文件进沙箱 → new OpenFileRequest → 写入 enableEdit →(可选)策略/管控 → 开启关闭回传 → sendRequest用户关闭 WPS → Promise 才带着 result.data 回来。

层级 能力 入口
接入 注册、可选序列号 registerApp / setWpsFileToken
打开 拉起、只读/可编辑 enableEdit
结果 关窗回传 enableTransferFile / wpsTransferType

未开启回传时,sendRequest 在拉起成功后即可返回 OK,且 data 常为空------这是正常行为,不要当成失败。开启回传后,Promise 会等到用户真正关闭文档。

二、字段语义与优先级

字段 作用
enableTransferFile = true 以 URI 方式回传(便捷开关)
wpsTransferType = TransferType.URI 明确 URI 回传
wpsTransferType = TransferType.FD FD 回传,关注 ResultData.transferFd

wpsTransferType 优先级高于 enableTransferFile。封装时建议只走 wpsTransferType,避免两套开关互相覆盖造成联调困惑。

typescript 复制代码
import { TransferType, OpenFileRequest } from '@wps/wps_sdk';

function enableCloseTransfer(req: OpenFileRequest, mode: 'uri' | 'fd'): void {
  req.wpsTransferType = mode === 'fd' ? TransferType.FD : TransferType.URI;
  // 不必再写 enableTransferFile;类型字段已足够表达意图
}

三、Result 与 ResultData

sendRequest 返回的 Result 中,关闭回传相关数据在 dataResultData):

字段 URI 模式 FD 模式
fileUri WPS 侧路径(须再拷贝) 可能无
transferFd --- 文件描述符
transferFileName / transferFileSize --- 常在 parameters 或同级字段

关键点:URI 回传的路径位于 WPS 沙箱 ,不能直接当本应用持久路径用。须拷贝到本应用沙箱后,得到可供后续上传、归档的 filePath

四、URI:拷贝到本应用沙箱

typescript 复制代码
import fs from '@ohos.file.fs';
import fileuri from '@ohos.file.fileuri';

function copyWpsUriToSandbox(ctx: UIAbilityContext, wpsFileUri: string): string | undefined {
  const file = fs.openSync(wpsFileUri, fs.OpenMode.READ_ONLY);
  if (!file.path) {
    return undefined;
  }
  const fileName = file.path.substring(file.path.lastIndexOf('/') + 1);
  const dir = `${ctx.filesDir}/wps_callback/${Date.now()}/`;
  if (!fs.accessSync(dir)) {
    fs.mkdirSync(dir, true);
  }
  const backupPath = dir + fileName;
  fs.copyFileSync(file.fd, backupPath);
  return fileuri.getUriFromPath(backupPath);
}

拷贝成功后,若业务约定需要清理 WPS 侧临时文件,再按对接文档建议删除;清理失败应打日志,不要吞掉主流程结果。

五、FD:从描述符写入沙箱

typescript 复制代码
function copyFdToSandbox(ctx: UIAbilityContext, parameters: Record<string, Object>): string | undefined {
  const fdParam = parameters['transferFd'] as Record<string, Object> | undefined;
  if (!fdParam || fdParam['type'] !== 'FD') {
    return undefined;
  }
  const fd = fdParam['value'] as number;
  const fileName = (parameters['transferFileName'] as string) || 'edited_file';
  if (fd < 0) {
    return undefined;
  }
  const localDir = `${ctx.filesDir}/fd_transfer/`;
  if (fs.accessSync(localDir)) {
    fs.rmdirSync(localDir);
  }
  fs.mkdirSync(localDir, true);
  const localPath = localDir + fileName;
  const localFile = fs.openSync(localPath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY | fs.OpenMode.TRUNC);
  const chunk = new ArrayBuffer(64 * 1024);
  while (true) {
    const len = fs.readSync(fd, chunk);
    if (len <= 0) break;
    fs.writeSync(localFile.fd, chunk, { length: len });
  }
  fs.closeSync(localFile.fd);
  fs.closeSync(fd);
  return fileuri.getUriFromPath(localPath);
}

FD 模式要记得关闭描述符,避免泄漏。文件名优先用回传参数里的名字,便于业务侧归档。

六、可复用打开封装

把是否回传、回传模式收进 Facade,页面不直接拼字段。

typescript 复制代码
export async function openEditableWithTransfer(
  ctx: UIAbilityContext,
  src: string,
  mode: 'uri' | 'fd' = 'uri'
): Promise<{ result: Result; localPath?: string }> {
  await prepareWps(APP_KEY, APP_SECRET);
  const path = copyToSandbox(ctx, src);
  const req = new OpenFileRequest(ctx, path);
  req.enableEdit = true;
  req.wpsTransferType = mode === 'fd' ? TransferType.FD : TransferType.URI;

  const result = await WPSApi.sendRequest(req);
  if (result.code !== ResultCode.OK || !result.data) {
    return { result };
  }
  let localPath: string | undefined;
  if (mode === 'fd' && result.data.parameters) {
    localPath = copyFdToSandbox(ctx, result.data.parameters);
  } else if (result.data.fileUri) {
    localPath = copyWpsUriToSandbox(ctx, result.data.fileUri);
  }
  return { result, localPath };
}

未开回传的预览路径,不要误用这套等待语义;否则用户不关文档,调用方会一直挂起。

七、联调表与小结

现象 优先查
Promise 很久不返回 是否开了回传、用户是否已关文档
OK 但 data 是否未开回传(属正常)
fileUri 但后续读失败 是否未拷贝到本应用沙箱
FD 无效 transferFd、parameters 结构、是否已 close
抛异常 / 1013 注册、凭据、包名、clean

日志固定:code / msg / 是否开回传 / 模式 / 是否已得到本应用路径。全仓 new OpenFileRequest 命中保持一处。换 HAR 后 clean;Release 不打印 secret。

HarmonyOS 上关闭回传是结果层能力:显式设置 wpsTransferType(或 enableTransferFile),等待关窗,再把 WPS 沙箱内容落到本应用沙箱。字段语义以官方对接文档为准。

接入评审确认:HAR、沙箱目录、回传模式是否统一走 Facade、正式包包名。缺一环易「本地绿、上架红」。真机验收:可编辑 + URI 回传拷贝成功;可选再验 FD。把「先打开绿,再开回传,再拷贝」写进联调清单,联调会从猜原因变成对表排查。周五用正式包包名再验注册与关窗回传各一次。注释写清「回传结果必须先拷贝再给业务」,比口头说「参考 Demo」更耐看。

从协作看,超时与取消策略要提前约定:用户长时间不关文档时,UI 是否提示、是否允许取消等待。拷贝目录建议按时间戳隔离,避免并发覆盖。FD 与 URI 不要在同一页面混用两套解析而无分支。路径拷贝失败要有独立错误提示,勿与「打开失败」混单。把上述约定坚持几周,回传相关反复提问通常会下降,接入节奏也会更稳。

再补验收与工程习惯。关文档后先确认日志里出现 fileUri 或有效 fd,再确认本应用沙箱目录生成了新文件,最后才走上传或归档。只断言「Promise 结束」不够接近真实闭环。并发打开两份文档时,两个时间戳目录都应存在且互不覆盖。FD 模式核对文件名、大小与可读性,并确认描述符已关闭。清理临时文件失败不应把用户带到失败页------本应用路径已经可用。联调反馈请带上:是否开回传、模式、是否已拷贝。周五再用正式包包名过一遍注册与 URI 回传用例,确认没有回退。预设名或封装函数名建议用业务语言(如 openAndCollect),方便产品与测试对齐「关窗拿结果」这条链路。


基于 WPS Open SDK 鸿蒙版对接实践整理,仅供开发者参考。

官方对接文档:https://365.kdocs.cn/l/clQl5cek2NoT

相关推荐
math_hongfan1 小时前
鸿蒙多模态AI交互高级:图文+语音+手势融合交互/多模态大模型端侧适配/跨模态检索高阶实战
人工智能·学习·华为·交互·语音识别·harmonyos·鸿蒙
云端漫步19871 小时前
HarmonyOS NEXT AI 智能生活助手:源码解析与项目复盘
人工智能·华为·生活·harmonyos
math_hongfan2 小时前
鸿蒙AI应用性能高级评测:推理延迟/内存占用/功耗/准确率四维指标评测体系与极致调优方案
人工智能·学习·华为·harmonyos·鸿蒙
FreeTinker12 小时前
wps云盘私有云解决的是企业文档协同,文件共享可以更轻
wps
less_1213812 小时前
HarmonyOS WPS Open SDK:打开时配置水印与修订模式
华为·harmonyos·wps
HarmonyOS_SDK16 小时前
差异化推送消息能力,助力腕上支付业务闭环
harmonyos
小雨青年19 小时前
【HarmonyOS 7 沉浸光感深度实战】 03 五档 ImmersiveStyle 到底怎么选
华为·harmonyos
云端漫步198720 小时前
HarmonyOS NEXT AI 智能生活助手:性能优化
华为·性能优化·生活·harmonyos
云端漫步198720 小时前
HarmonyOS NEXT AI 智能生活助手:统一 AIService 封装
人工智能·华为·生活·harmonyos