《HarmonyOS技术精讲-Basic Services Kit》打印服务:文档与图片打印
《HarmonyOS技术精讲-Basic Services Kit》打印服务文档与图片打印开篇打印功能在HarmonyOS上怎么用HarmonyOS NEXT 开发里ohos.print这个 API 经常被误用。很多人第一次接触打印能力时会发现官方示例能运行但换成自己的图片或 HTML 文档要么打印出来空白要么预览界面根本弹不出来。打印这个功能本身不复杂——无非是把内容传给系统打印框架然后用户选打印机、调参数、点确认。但真正麻烦的是数据格式转换和生命周期管理。比如用PrintDocumentAdapter自定义打印内容时回调时机和页面销毁之间的冲突就很容易丢数据。这篇文章把打印图片和打印 HTML 文档的完整实现走一遍同时会重点说明那些官方文档里一笔带过、但实际项目里天天踩的坑。打印服务解决什么问题ohos.print模块提供了将文本、图片、PDF 等内容发送到物理打印机或虚拟打印机的统一接口。它解决的是“应用内内容如何变成纸面输出”的问题。适用场景场景说明图片打印相册、截图、证件照等文档打印收据、订单、报告PDF 打印合同、说明书自定义内容打印用 HTML 模板生成的定制内容不适用的场景需要直接操作打印机硬件参数如进纸器、切纸刀的场景Print Kit 不提供这种底层能力。大量批量打印几十上百页建议走后台任务而不是直接在 UI 线程触发。环境说明DevEco Studio 版本DevEco Studio 6.1.0 及以上 HarmonyOS SDK 版本HarmonyOS 6.1.0(23) 及以上 目标设备手机 / 平板核心实现1. 打印一张图片思路是把图片文件转为PixelMap然后通过systemPrint.PrintDocumentAdapter的onStartLayoutWritePage回调写入打印页面。代码实现importimagefromohos.multimedia.image;import{systemPrint}fromohos.print;import{BusinessError}fromohos.base;// 打印单张图片asyncfunctionprintImage(context:Context,imagePath:string):Promisevoid{// step1: 从文件读取图片constfileUriimagePath.startsWith(file://)?imagePath:file://imagePath;constimageSourceimage.createImageSource(fileUri);constpixelMapawaitimageSource.createPixelMap();// step2: 构造打印任务constprintJobsystemPrint.createPrintJob({taskName:PrintImage,adapter:newPrintImageAdapter(pixelMap)});// step3: 启动打印预览printJob.start((err:BusinessError){if(err){console.error(print failed,JSON.stringify(err));}});}// 自定义 PrintDocumentAdapterclassPrintImageAdapterextendssystemPrint.PrintDocumentAdapter{privatepixelMap:image.PixelMap;constructor(pixelMap:image.PixelMap){super();this.pixelMappixelMap;}onStartLayoutWritePage(params:any,callback:(result:any)void):void{// 写入一页图片constpage{index:0,width:params.pageSize.width,height:params.pageSize.height,content:this.pixelMap};callback({result:0,// 0 表示成功pages:[page]});}onFinish():void{// 清理资源this.pixelMapnull;}}关键点说明image.createImageSource只接收文件路径file://或沙箱路径不能直接传网络地址。网络图片需要先下载到本地。onStartLayoutWritePage回调里的params.pageSize是系统根据用户选择的纸张类型自动计算的不要硬编码。每页只能写一个content如果图片很大建议提前缩放否则内存容易涨上去。2. 打印一个 HTML 文档HTML 打印更直接系统内部会帮我们解析样式和布局不需要自己处理PixelMap。代码实现import{systemPrint}fromohos.print;import{BusinessError}fromohos.base;// 打印 HTML 字符串asyncfunctionprintHtmlDocument(context:Context):Promisevoid{consthtmlContenthtml body h1Hello HarmonyOS/h1 p这是一段测试打印的 HTML 内容。/p table border1 trtd项目/tdtd数量/td/tr trtd商品A/tdtd2/td/tr /table /body /html;constprintJobsystemPrint.createPrintJob({taskName:PrintHTML,adapter:newHtmlPrintAdapter(htmlContent)});printJob.start((err:BusinessError){if(err){console.error(print failed,JSON.stringify(err));}});}classHtmlPrintAdapterextendssystemPrint.PrintDocumentAdapter{privatehtml:string;constructor(html:string){super();this.htmlhtml;}onStartLayoutWritePage(params:any,callback:(result:any)void):void{// HTML 内容直接作为字符串传给 contentcallback({result:0,pages:[{index:0,width:params.pageSize.width,height:params.pageSize.height,content:this.html}]});}}注意事项HTML 中引用的 CSS 和图片需要是内联的不支持外部资源加载。也就是说link和img srchttp://...不会生效。表格布局、字体、颜色等 CSS 属性基本都支持但浮动和定位效果可能会有偏差建议打印前在真机上预览一下效果。如果 HTML 内容超过一页系统会自动分页不需要手动处理分页逻辑。3. 页面调用在页面上加一个按钮点击后触发打印EntryComponentstruct PrintDemo{privatecontext:ContextgetContext(this);build(){Column(){Button(打印图片).onClick((){// 沙箱路径示例实际使用时替换为真实图片路径constpaththis.context.filesDir/test.png;printImage(this.context,path);}).margin(20)Button(打印 HTML).onClick((){printHtmlDocument(this.context);})}.width(100%).height(100%).justifyContent(FlexAlign.Center)}}踩坑记录坑1打印预览界面一闪而过现象调用printJob.start后打印预览界面闪一下就消失了没有进入正式打印流程。原因PrintDocumentAdapter的onStartLayoutWritePage回调中如果pages数组为空或content为 null系统会认为打印任务无效直接关闭预览。解决方案确保回调里pages数组至少有一个元素而且content不能为 null。如果content是PixelMap先检查pixelMap是否已释放。onStartLayoutWritePage(params:any,callback:(result:any)void):void{if(!this.pixelMap){console.error(pixelMap is null, print aborted);callback({result:-1,pages:[]});return;}// 正常处理}坑2打印 PDF 时页面方向不生效现象设置了orientation: landscape但 PDF 打印出来还是纵向。原因PrintDocumentAdapter的onStartLayoutWritePage参数里pageSize的宽高是由系统根据纸张类型和用户设置决定的在回调里手动改width和height会被忽略。解决方案在创建打印任务时使用PrintAttributesBuilder设置方向。constattributesnewsystemPrint.PrintAttributesBuilder().setOrientation(systemPrint.PrintOrientation.LANDSCAPE).build();constprintJobsystemPrint.createPrintJob({taskName:PrintPDF,adapter:adapter,attributes:attributes});最佳实践图片打印前先预读取宽高如果图片尺寸很大比如 4000x3000建议在onStartLayoutWritePage中等比缩放否则打印出的图像可能被截断。缩放方式用pixelMap.scale不要重新createPixelMap后者会额外占用内存。非必要不自定义 PrintDocumentAdapter如果只是打印本地图片或 PDF直接用systemPrint.print方法更简单它会自动处理适配器逻辑。只有需要动态生成打印内容如拼接多张图、叠加水印时才需要自定义。打印任务结束后及时清理资源onFinish回调里要释放PixelMap、关闭文件流。如果页面销毁时打印任务还没结束要把PrintJob的引用置为 null避免内存泄漏。常见问题FAQQ为什么真机可以正常打印模拟器点预览没反应A模拟器没有真实的打印服务预览界面可能无法正确弹出。建议在 API 23 以上版本的真机上测试。Q打印任务已经开始用户突然退出页面会怎样A页面销毁后PrintJob的引用会变为空打印预览界面会自动关闭但已提交的打印任务会继续由系统处理。如果需要取消可以在页面的aboutToDisappear中调用printJob.cancel()。Q打印 HTML 时中文显示为乱码AHTML 文档需要指定charset在head中加入meta charsetUTF-8。如果还有乱码检查 HTML 字符串的编码格式确保 UTF-8 编码。如果你也遇到类似问题可以重点检查回调中的content是否有效以及打印任务的生命周期管理。官方文档对PrintDocumentAdapter的行为描述得比较简略建议结合实际运行效果一起验证。不同设备上的打印行为可能存在差异建议真机测试。

相关新闻

《HarmonyOS技术精讲-Basic Services Kit》升级服务:应用内更新检测与下载安装

《HarmonyOS技术精讲-Basic Services Kit》升级服务:应用内更新检测与下载安装

《HarmonyOS技术精讲-Basic Services Kit》升级服务:应用内更新检测与下载安装这个问题在开发里比较常见 HarmonyOS NEXT 开发里,升级服务 API 的调用频率其实很高,但很多人第一次接触时会发现:官方示例能跑通,放到实际…

2026/7/18 20:48:23阅读更多 →
朱雀检测从89%直降0%,我试了30篇稿子才摸透这AIGC检测的套路

朱雀检测从89%直降0%,我试了30篇稿子才摸透这AIGC检测的套路

不说废话,直接开干。朱雀大模型检测准确率95%,硬刚没用,绕过去才是本事。下面6招,招招可抄。 第一件事:知道检测系统在抓什么(说清楚就过) 不扯原理,两个核心指标: ① …

2026/7/18 20:48:23阅读更多 →
后端:SpringBoot 前端:Vue.js 数据库:MySQL 8.0 社区养老服务老人帮扶系统 社区养老服务springboot老人帮扶系统vue前后分离Java源码mysql

后端:SpringBoot 前端:Vue.js 数据库:MySQL 8.0 社区养老服务老人帮扶系统 社区养老服务springboot老人帮扶系统vue前后分离Java源码mysql

智慧-社区养老服务springboot老人帮扶系统vue前后分离Java源码mysql本项目是一个基于Spring Boot和Vue.js的社区养老服务管理系统,旨在提升社区养老服务的质量与效率。系统从前端到后端全栈开发,前端采用Vue.js构建直观易用的用户界面,后端使…

2026/7/18 20:46:22阅读更多 →
DMA控制器原理与实战:嵌入式系统数据搬运优化指南

DMA控制器原理与实战:嵌入式系统数据搬运优化指南

1. DMA控制器:嵌入式系统的“数据搬运工”在嵌入式系统开发中,尤其是涉及雷达信号处理、高速数据采集或实时图像处理的场景,我们常常会遇到一个核心矛盾:CPU的计算能力是宝贵的,但大量、频繁的数据搬运工作&#xff08…

2026/7/18 22:00:49阅读更多 →
杭州积分落户加分攻略:学历提升如何为你的城市生活加分

杭州积分落户加分攻略:学历提升如何为你的城市生活加分

一、杭州积分落户政策:新市民的安居之路作为长三角地区最具吸引力的城市之一,杭州以其优美的自然环境、蓬勃的经济活力和开放包容的城市氛围,每年吸引着大量外来人口前来就业和定居。为了更好地服务外来常住人口,杭州实行了积分落…

2026/7/18 22:00:49阅读更多 →
搜索场景的大模型推理优化:多阶段召回的精排融合与 Query 理解延迟压缩

搜索场景的大模型推理优化:多阶段召回的精排融合与 Query 理解延迟压缩

搜索场景的大模型推理优化:多阶段召回的精排融合与 Query 理解延迟压缩 一、搜索的全链路延迟分解:从 Query 输入到结果返回的三级跳 搜索系统的一个完整请求链路包含三个阶段:Query 理解(意图分类、实体识别、纠错、改写&#xf…

2026/7/18 22:00:49阅读更多 →
高性能日志系统的架构演进:从磁盘 IOPS 瓶颈到零拷贝环形缓冲区的工程实践

高性能日志系统的架构演进:从磁盘 IOPS 瓶颈到零拷贝环形缓冲区的工程实践

高性能日志系统的架构演进:从磁盘 IOPS 瓶颈到零拷贝环形缓冲区的工程实践 一、日志的隐性性能杀手:为什么 1000 QPS 的日志打印能拖垮 10000 QPS 的服务 日志是系统的观察者,但它不应该成为系统的拖累者。通过对一个 Go 微服务做火焰图分析&…

2026/7/18 22:00:49阅读更多 →
【Java基础】分支结构与循环语句 超详细笔记(零基础易懂)

【Java基础】分支结构与循环语句 超详细笔记(零基础易懂)

📚 专栏:Java零基础入门笔记 ✨ 前言 程序的核心运行逻辑离不开三大流程控制结构:顺序结构、分支结构、循环结构。几乎所有复杂业务代码,都是基于这三种基础结构嵌套组合实现的。本篇笔记整理了Java中所有分支、循环语法的核心知识…

2026/7/18 22:00:49阅读更多 →
多人协作内容总是版本混乱?科会通等3款工具实测与使用指南

多人协作内容总是版本混乱?科会通等3款工具实测与使用指南

多人协作内容总是版本混乱、信息不同步?作为团队负责人,在推进跨部门项目时,最头疼的往往是会议纪要和文档在微信群里反复传递,导致最终版本难以统一。为了解决这一痛点,本文以iOS系统生态为例,实测科会通、…

2026/7/18 21:58:49阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/18 10:49:13阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/18 8:49:08阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/18 14:49:24阅读更多 →
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…

2026/7/18 0:00:14阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:14阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

2026/7/18 0:00:14阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/17 22:48:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →