react-native-html-to-pdf:基于 React Native OpenHarmony 的 HTML 转 PDF 原生插件项目

将 HTML 字符串转换为 PDF 文档

Branch3Tags2

react-native-html-to-pdf

本项目基于 react-native-html-to-pdf 开发。如果在使用过程中有任何问题,欢迎在 GitCode 提交 Issue,会及时跟进。

项目介绍

@hxa-rn/react-native-html-to-pdf 是 react-native-html-to-pdf 的鸿蒙(OpenHarmony)适配版本,当前版本 1.3.1。

本库为含原生实现的 TurboModule 插件,通过 ArkWeb 渲染 HTML 字符串并调用 createPdf 生成 PDF 文档,支持自定义页面尺寸、文件名与输出目录、Base64 输出、背景色、相对资源加载及页数统计。JS 侧 API 与原库保持一致,业务代码无需修改 import 路径。

集成指南

安装

npm install @hxa-rn/react-native-html-to-pdf

依赖要求

依赖 版本要求
react *(peerDependency)
react-native >=0.72(peerDependency)
Node.js >=18

业务代码仍使用原库名 react-native-html-to-pdf 导入(harmony.alias),RNOH 自动重定向至 @hxa-rn/react-native-html-to-pdf:

import { generatePDF } from 'react-native-html-to-pdf';

Autolinking

本模块支持 Autolinking,安装后由 RNOH 自动链接 HtmlToPdfPackage(C++/ETS 双注册),HAR 位于 harmony/html_to_pdf/,CMake 目标名为 html_to_pdf。

若 Autolinking 未生效,可按以下备选步骤手动注册 Package:

C++ 侧(PackageProvider.cpp):

#include "HtmlToPdfPackage.h"
// ...
std::make_shared<rnoh::HtmlToPdfPackage>(ctx),

ETS 侧(RNPackagesFactory.ets):

import HtmlToPdfPackage from '@hxa-rn/react-native-html-to-pdf';
// ...
new HtmlToPdfPackage(ctx),

宿主接入要求(必须)

本模块为纯 TurboModule 无 UI,WebviewController 必须绑定 UI 树中的 Web 组件才能调用 loadData / createPdf。宿主必须完成以下三步,否则 convert 返回 WEBVIEW_ERROR,或超时后后续转换被阻塞。完整参考实现见 example/harmony/entry/src/main/ets/ 与 example_auto/harmony/entry/src/main/ets/。

1. EntryAbility:初始化 Web 引擎并启用多渲染进程

顺序不可颠倒:必须先 initializeWebEngine(),再 setRenderProcessMode(MULTIPLE)。

import { webview } from '@kit.ArkWeb';
import { AbilityConstant, Want } from '@kit.AbilityKit';

onCreate(want: Want, launchParam?: AbilityConstant.LaunchParam) {
  super.onCreate(want, launchParam);
  webview.WebviewController.initializeWebEngine();
  webview.WebviewController.setRenderProcessMode(webview.RenderProcessMode.MULTIPLE);
}

2. Index.ets:声明隐藏 Web 并注入 Controller

HtmlToPdfConverter 为 HAR 默认入口的具名导出。resetPdfWebController / retirePdfWebController 是宿主方法(不是本库 API),用于超时后重叠挂载新 Web;完整实现见 example/harmony/entry/src/main/ets/pages/Index.ets。

import { webview } from '@kit.ArkWeb';
import { HtmlToPdfConverter } from '@hxa-rn/react-native-html-to-pdf';

Web({ src: 'about:blank', controller: controller })
  .width(1)
  .height(1)
  .visibility(Visibility.Hidden)
  .onControllerAttached(() => {
    HtmlToPdfConverter.getInstance().bindController(controller, (): void => {
      this.resetPdfWebController();
    });
  })
  .onPageEnd((event) => {
    HtmlToPdfConverter.getInstance().onPageEnd(event.url, controller);
  })
  .onRenderExited(() => {
    HtmlToPdfConverter.getInstance().onRenderProcessGone(controller);
    this.retirePdfWebController(generation);
  })

3. 超时/取消后:重叠挂载新 Web

ArkWeb 的 createPdf 不可取消;库在 30s 超时后会通过 recoveryHandler 请求宿主重建 Web。宿主需保留旧 Web 仍挂载,同时创建并挂载新 WebviewController(ForEach 多实例),在新 Web 的 onControllerAttached 中再次 bindController,旧 Web 触发 onRenderExited 后再从 UI 树移除。

使用说明

import { generatePDF, type PDFOptions, type PDFResult } from 'react-native-html-to-pdf';

async function createPDF() {
  const options: PDFOptions = {
    html: '<h1>PDF TEST</h1><p>Hello HarmonyOS</p>',
    fileName: 'test',
    base64: true,
    width: 612,
    height: 792,
    directory: 'reports',
    baseURL: 'https://example.com/',
    bgColor: '#ffffff',
    shouldPrintBackgrounds: true,
  };

  try {
    const result: PDFResult = await generatePDF(options);
    console.log(result.filePath);
    console.log(result.numberOfPages);
    console.log(result.base64);
  } catch (e) {
    const err = e as { code?: string; message?: string };
    console.log(err.code, err.message);
  }
}

错误处理:generatePDF 失败时 reject 的结构化错误包含 code 与 message 字段,常见错误码见接口文档。

接口文档

generatePDF(options: PDFOptions): Promise<PDFResult>

将 HTML 字符串渲染为 PDF 文件并写入应用沙箱,返回文件路径及可选的 Base64 编码与页数。

底层 TurboModule 方法名为 HtmlToPdf.convert,JS 层通过 generatePDF 封装并统一错误格式。

PDFOptions

参数 类型 必填 说明
html string 是 HTML 字符串;空字符串或非字符串类型返回 INVALID_HTML
fileName string 否 输出文件名(不含 .pdf 后缀);缺省自动生成 PDF_<UUID>;非法字符返回 INVALID_FILENAME
width number 否 页面宽度(磅);缺省 612
height number 否 页面高度(磅);缺省 792
base64 boolean 否 为 true 时在结果中返回 PDF 的 Base64 编码
padding number 否 页面边距(iOS Only,鸿蒙端不生效)
paddingTop number 否 上边距(iOS Only,鸿蒙端不生效)
paddingBottom number 否 下边距(iOS Only,鸿蒙端不生效)
paddingLeft number 否 左边距(iOS Only,鸿蒙端不生效)
paddingRight number 否 右边距(iOS Only,鸿蒙端不生效)
bgColor string 否 十六进制背景色;通过注入 HTML body 背景样式实现
directory string 否 相对应用 filesDir 的子目录;缺省使用 cacheDir;目录创建失败返回 FOLDER_ERROR
baseURL string 否 HTML 相对资源(图片/样式)的加载基准地址
shouldPrintBackgrounds boolean 否 是否打印 CSS 背景;透传至 PdfConfiguration.shouldPrintBackground

PDFResult

字段 类型 说明
filePath string 生成的 PDF 文件绝对路径
base64 string 可选;base64: true 时返回 PDF 的 Base64 编码
numberOfPages number 可选;PDF 页数;依赖 PDF Kit 解析,失败时不返回该字段

错误码

错误码 说明
INVALID_HTML HTML 为空、未传或非字符串
INVALID_FILENAME 文件名含非法路径字符
FOLDER_ERROR 输出目录创建失败
CONVERSION_IN_PROGRESS 上一次转换尚未完成
PDF_CONVERSION_TIMEOUT 单次转换超过 30 秒
WEBVIEW_ERROR Web 组件未绑定或 loadData 失败
PDF_WRITE_ERROR PDF 文件写入失败
PDF_GENERATION_ERROR 其他 PDF 生成异常

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 18(运行 Example 建议 >= 20,见 example/package.json)
DevEco Studio 5.0+ / 6.0+
HarmonyOS SDK API 13+(example/harmony 的 compatibleSdkVersion 为 5.0.1(13))

运行步骤

1. 克隆仓库

git clone https://gitcode.com/hxa-rn/react-native-html-to-pdf.git
cd react-native-html-to-pdf
git checkout main

2. 进入 example 目录,安装依赖

cd example
npm install --legacy-peer-deps

Example 已改为从 npm 公仓安装 @hxa-rn/react-native-html-to-pdf@^1.3.1,不再使用本地 file:../xxx.tgz,运行 Example 不必再执行 npm pack。

3. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

4. 安装鸿蒙依赖

cd harmony
ohpm install

5. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio
  • 选择 example/harmony 目录
  • 首次构建请在 File → Project Structure → Signing Configs 勾选 Automatically generate signature,Apply 后 Sync
  • 等待 Sync 完成

6. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备/模拟器。

注意:Example 已预置 Autolinking Package 注册、Metro alias 与 HAR 依赖,无需手动 Link。编 HAP 前必须先执行 npm run dev。createPdf 为 API 14+ 能力,请在 HarmonyOS 5.1+(API 14 及以上)真机或模拟器上验证。

约束与限制

兼容性

项目 要求
React Native / RNOH RN >=0.72;框架基线 RNOH 0.72
Node.js >=18(运行 Example 建议 >=20)
HarmonyOS SDK 编译 5.0.1(13)(example/harmony 的 compatibleSdkVersion);运行期 createPdf 需 API 14+(HarmonyOS 5.1+)
运行期最低系统 API 14(HarmonyOS 5.1+):createPdf 为 API 14+ 能力,API 13 及以下设备运行期抛能力不支持错误

权限

插件 HAR(harmony/html_to_pdf/src/main/module.json5)声明:

权限 用途
ohos.permission.INTERNET ArkWeb 通过 baseURL 加载网络相对资源

平台差异与已知限制

  • padding / paddingTop / paddingBottom / paddingLeft / paddingRight 为 iOS Only 参数,鸿蒙端不生效(与 Android 行为一致)。
  • numberOfPages 依赖 PDF Kit(@kit.PDFKit),官方仅支持中国大陆(港澳台除外);解析失败时该字段不返回,不影响 PDF 生成主流程。
  • bgColor 通过注入 HTML body 背景样式 + shouldPrintBackground=true 实现;若 HTML 自带 body 背景样式可能互相覆盖。
  • width / height 单位为磅,鸿蒙端按 1 磅 = 1/72 英寸换算为 PdfConfiguration 英寸单位;非法或缺省尺寸按默认 612×792 磅处理。
  • 单次转换 30s 超时保护;转换进行中再次调用返回 CONVERSION_IN_PROGRESS。
  • createPdf 不可取消;超时后须宿主配合 Web 重建(见集成指南第 3 步)。
  • base64: true 时整文件读入编码,超大文件有内存峰值风险。

开源license

本项目基于 MIT 协议,详见 LICENSE 文件。

问题反馈渠道

Introduction

将 HTML 字符串转换为 PDF 文档

Customize your domain