特别注意:关键避坑点
要在鸿蒙应用中预览沙箱路径下的 .docx 文件,核心是使用 PreviewKit 并严格遵循 URI 格式、权限配置和 MIME 类型规范,以下是可直接运行的完整代码和避坑指南(适配 API 10+,HarmonyOS 5.0+)
一、前置配置(必须完成)
1. 权限声明(module.json5)
需要申请文件读写权限,并引入 PreviewKit 模块:
{
"module": {
// 权限声明
"requestPermissions": [
{ "name": "ohos.permission.READ_USER_STORAGE" },
{ "name": "ohos.permission.WRITE_USER_STORAGE" }
],
// 引入预览工具包
"usesModules": [
{ "name": "@kit.PreviewKit" }
]
}
}
2. 动态申请权限(可选,高版本鸿蒙需动态授权)
在页面初始化时申请存储权限,避免预览时因权限不足失败:
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
// 权限申请函数
async requestStoragePermission() {
const atManager = abilityAccessCtrl.createAtManager();
const permissions = ['ohos.permission.READ_USER_STORAGE'];
try {
const grantStatus = await atManager.checkAccessToken(
abilityAccessCtrl.createTokenID(
this.uiContext.abilityInfo.bundleName,
this.uiContext.abilityInfo.applicationInfo.uid
),
permissions[0]
);
if (grantStatus !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
// 申请权限
await atManager.requestPermissionsFromUser(this.uiContext, permissions);
}
} catch (err) {
console.error('权限申请失败:', err);
}
}
二、完整 ArkTS 实现代码
import { filePreview } from '@kit.PreviewKit';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
@Entry
@Component
struct DocxPreviewPage {
// 获取 UI 上下文
private uiContext = getContext(this) as common.UIAbilityContext;
// 目标文件名称
private docFileName = '关于 2023 年元旦及春节假期安排的预通知.docx';
// 沙箱内文件绝对路径
private docFilePath = `/data/storage/el2/base/haps/entry/files/${this.docFileName}`;
build() {
Column({ space: 20, alignItems: ItemAlign.Center })
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center) {
Button('预览 Word 文档')
.width(200)
.height(50)
.onClick(async () => {
// 先申请权限
await this.requestStoragePermission();
// 执行预览
this.previewDocxFile();
})
}
}
// 核心预览方法
private previewDocxFile() {
// 1. 校验文件是否存在
if (!fs.accessSync(this.docFilePath)) {
console.error(`文件不存在:${this.docFilePath}`);
return;
}
// 2. 构造 标准 URI(关键!必须带应用包名)
const appBundleName = this.uiContext.abilityInfo.bundleName;
const fileUri = `file://${appBundleName}${this.docFilePath}`;
// 3. 配置预览参数
const previewParam: filePreview.PreviewInfo = {
title: this.docFileName, // 预览窗口标题
uri: fileUri, // 带包名的文件 URI
// docx 格式的标准 MIME 类型(不可写错)
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
};
// 4. 调用系统预览接口
filePreview.openPreview(this.uiContext, previewParam)
.then(() => console.info('预览启动成功'))
.catch((err: BusinessError) => {
console.error(`预览失败:错误码=${err.code},原因=${err.message}`);
});
}
// 动态申请存储权限
private async requestStoragePermission() {
const atManager = abilityAccessCtrl.createAtManager();
const permissions = ['ohos.permission.READ_USER_STORAGE'];
try {
const tokenId = abilityAccessCtrl.createTokenID(
this.uiContext.abilityInfo.bundleName,
this.uiContext.abilityInfo.applicationInfo.uid
);
const grantStatus = await atManager.checkAccessToken(tokenId, permissions[0]);
if (grantStatus !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
await atManager.requestPermissionsFromUser(this.uiContext, permissions);
}
} catch (err) {
console.error('权限申请异常:', err);
}
}
}
三、关键避坑点(90% 失败原因在这里)
1.URI 格式必须正确
- ❌ 错误写法:
file:///data/storage/el2/...(缺少应用包名) - ✅ 正确写法:
file://{应用包名}/data/storage/el2/... - 动态获取包名:
this.uiContext.abilityInfo.bundleName,避免硬编码。
2.MIME 类型不能混淆
|-------|-------------------------------------------------------------------------|----------------------------------|
| 文件类型 | 正确 MIME 类型 | 错误 MIME 类型 |
| .docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document | application/msword(这是 .doc 格式) |
3.文件路径校验
- 用
fs.accessSync(filePath)提前判断文件是否存在,避免因文件未拷贝到沙箱路径导致失败。 - 若文件是从外部导入,需先通过
fileIo将文件写入entry/files目录。
4.低版本兼容(API < 10)
低版本鸿蒙无 PreviewKit,需通过 隐式 Want 调用 WPS 等第三方应用打开:
private openByThirdApp() {
const want = {
action: 'ohos.want.action.viewData',
uri: this.fileUri,
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
};
this.uiContext.startAbility(want).catch(err => console.error('调用第三方失败:', err));
}
四、常见问题排查
|---------------|----------------------------------------|
| 问题现象 | 排查方向 |
| 预览无响应,错误码 -1 | 检查 URI 是否带应用包名 |
| 提示 "不支持的文件格式" | 核对 MIME 类型是否为 docx 专属 |
| 提示 "权限不足" | 检查 module.json5 权限声明 + 动态申请权限 |
| 提示 "文件不存在" | 确认文件已放入 entry/files 目录,路径拼写无空格 / 错别字 |