鸿蒙electron框架PC适配:ExifCleaner 适配鸿蒙全过程:一次从“能启动”到“能处理文件”的完整复盘
鸿蒙版 ExifCleaner 不再只是一个界面能打开的壳,而是开始具备真正处理文件的能力。这一步做出来之后,后面无论是继续补 RAW、补更深的视频 metadata,还是把 PDF 做得更完整,至少都已经站在一条可持续演进的路线上了。如果把这次工作浓缩成一句话,我会这样概括:鸿蒙适配最难的,从来不是把窗口拉起来,而是把桌面环境里那些理所当然的底层能力,重新在新平台上接回来。
一、这篇文章想讲什么
欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区 :https://harmonypc.csdn.net/
这篇文章不是单纯展示“我把一个 Electron 项目跑在鸿蒙上了”,而是想把一个更真实的问题讲清楚:
一个原本强依赖桌面环境能力的 Electron 应用,迁移到 OpenHarmony 之后,怎么一步一步从“可以打开界面”,走到“真的可以处理用户文件”。
这次选择的项目是 ExifCleaner。
如果只看表面,它只是一个界面很简洁的小工具:拖进去一批图片或者文档,清掉其中的 metadata,然后导出干净文件。
但真开始改的时候,很快就会发现它的难点根本不在界面,而在底层能力上。桌面版之所以好用,不是因为 Electron 写得多花哨,而是因为它背后站着一个非常强的工具:ExifTool。
问题也正出在这里。
ExifTool 本质上是 Perl 工具链,在桌面系统里问题不大,但到了鸿蒙这一侧,事情就完全变了。应用虽然能被拉起来,但真正做 metadata 处理时,很快就会出现进程起不来、资源路径不对、运行时依赖缺失、格式处理链断掉等一串问题。
所以这次适配的核心,不是“如何让 Electron 在鸿蒙显示一个窗口”,而是:
- 先把应用的主流程跑通。
- 再把原来依赖
ExifTool的那部分能力,一点点接管回来。 - 最后把高频格式覆盖到“日常可用”。
这篇文章就按这个过程展开。
该项目适配鸿蒙版本已经开源到:https://atomgit.com/lqjmac/exifcleaner-ohos
二、项目起点:窗口打开了,但功能几乎不可用
刚开始接这个项目的时候,最容易产生一种错觉:既然界面已经能起来,那是不是离“适配完成”就不远了?
实际完全不是。
应用在鸿蒙上首次跑起来以后,最早看到的问题不是 UI 样式错乱,而是一串比较扎眼的运行日志,比如:
ExifTool is not runningspawn /.resources/nix/bin/exiftool ENOENTstrings.json读取失败icon.png路径错误- 文件拖进来之后能看到列表,但 metadata 读取不出来
换句话说,应用表面上已经“活着”,但核心功能其实是断的。
ExifCleaner 的主链路很简单:
- 用户导入文件
- 读取原始 metadata
- 调用清理逻辑
- 再读取一次清理后的 metadata
- 在界面里展示 before / after 差异
而在鸿蒙上,断点恰好在第 2 步和第 3 步。因为这两步原来都建立在 ExifTool 可正常启动的前提上。
也就是说,如果不把 ExifTool 依赖替换掉,应用虽然能打开,但实际上没有办法完成自己的核心任务。

三、先不要急着谈“全量支持”,第一步是先把处理链接管下来
一开始我也想过两种路线:
路线一:继续想办法把桌面版 ExifTool 搬过去
这条路听起来最省事,因为理论上只要能把原来的 Perl 和资源包完整跑起来,桌面版大部分能力都能继承。
但问题是,这条路在鸿蒙上并不稳定,而且从长期看也不划算。
原因很直接:
- 运行时依赖重
- 资源路径和启动方式和桌面完全不同
- 即使勉强拉起来,后面维护成本也会很高
- 一旦要做打包和分发,问题只会更多
路线二:在鸿蒙侧重新接管 metadata 处理能力
最终我选择了这条路。
具体做法不是“一次性重写 ExifTool”,那也不现实,而是引入一个新的适配层:
HarmonyMetadataAdapter
这个适配层做的事情很明确:
- 桌面环境下,仍然走原来的
ExifToolAdapter - 鸿蒙环境下,切到
HarmonyMetadataAdapter
这样一来,应用上层的调用方式不用大改,改动点会被尽量控制在基础设施层。
这一步非常重要,因为它意味着项目开始从“强依赖桌面工具”转向“鸿蒙侧有自己的一套处理入口”。
说白一点,这一步不是为了功能一下子变全,而是为了把主动权拿回来。

四、第二个坑:资源路径在鸿蒙上不是桌面那一套
把 metadata 适配入口接出来之后,问题并没有结束。
很快又遇到另一个非常现实的问题:资源路径不对。
桌面 Electron 项目里,很多资源读取习惯上会假设路径长这样:
/.resources/icon.png/.resources/strings.json/.resources/nix/bin/exiftool
但鸿蒙打包出来以后,资源落点并不是这套路径结构。
实际调试时能看到,应用资源更像是被放到一层打包目录下面,比如:
/data/storage/el1/bundle/.../resources/resfile/resources/app/...
这就意味着,原来那些“默认以为资源就在某个相对目录”的写法,会在鸿蒙上大量失效。
这个阶段做的事情主要有两类:
- 统一资源路径解析逻辑
- 调整鸿蒙打包脚本,把应用运行真正需要的资源放进正确目录
这里我额外做了一个处理:在鸿蒙包里单独引入 app-resources 目录,用它来放图标、字符串文件和后续需要的资源。这样路径逻辑会比沿用桌面的隐藏目录更稳定一些。
这一步处理完以后,像 strings.json、icon.png、检查图标这些资源读取问题就明显少了很多,至少不会动不动出现“文件明明打进包里了,但运行时就是找不到”的情况。

五、先解燃眉之急:把最常用图片格式做成可用版
在适配这类工具时,我一直比较反对一上来就追求“支持一切格式”。更实用的做法是先问一个问题:
用户平时最常拿来清 metadata 的文件,到底是什么?
答案其实很明确,首先就是图片,尤其是:
JPG / JPEGPNG
所以前期工作的重点非常集中,就是先把这两条线做通。
JPEG 这条线做了什么
对 JPEG,我主要补了这几类能力:
- 识别
APP1 Exif - 识别
XMP - 识别
ICC Profile - 识别 IPTC / Photoshop IRB
- 清理 metadata 时支持:
- 全删
- 保留方向信息
- 保留 ICC 色彩配置
尤其是“保留方向”这一点,如果没有处理好,用户会觉得功能坏了。因为照片虽然 metadata 被清掉了,但图片方向突然不对了,体验上就会像是清理逻辑把文件搞坏了一样。
PNG 这条线做了什么
PNG 的情况和 JPEG 不太一样,重点在于各种 chunk:
eXIftEXtzTXtiTXtiCCPtIME
这部分做完以后,至少在鸿蒙上已经能比较稳定地处理截图、网络图片、带文本块的 PNG 文件了。

六、从“图片可用”走向“主流格式可用”
JPEG 和 PNG 打通之后,后面的工作就不再是“从零到一”,而更像是不断把同类文件体系往外扩。
1. WebP
WebP 相对清晰一些,主要处理:
EXIFXMPICCP
同时把 metadata 清理和保留色彩配置这部分一起补上。
2. HEIC / HEIF / AVIF
这几类格式是中期适配里非常关键的一段,因为手机拍照场景里它们的占比很高。
它们本质上都属于 ISO BMFF 容器家族,所以这一阶段的重点变成了:
- 解析
Exifbox - 解析
XMPbox - 递归处理容器结构
- 清理时重建 box 结构
- 保留 orientation
最开始这里踩过一个比较典型的坑:表面上已经“接了 HEIC 支持”,但一跑测试才发现 TIFF 偏移找错了,结果 Make/Model 根本读不出来。后来修掉这个偏移问题之后,HEIC/HEIF 才算真正进入可用状态。
AVIF 这块后面就顺势复用了 HEIF 这套能力,所以扩展起来比较快。
3. TIFF / DNG
TIFF 是另一个关键节点,因为它不只是一个普通图片格式,还直接关系到很多 RAW 体系的基础。
这部分除了基础 EXIF 读取,我还补了:
XMPICC_ProfilepreserveOrientationpreserveColorProfile
后面做 DNG 的时候,基本就是复用 TIFF 这条线。
4. GIF
GIF 这块没有前面那些格式复杂,但我也不想让它在鸿蒙上直接掉成“不支持”。所以这部分补的是:
- comment 扩展块
- application 扩展块
- XMP 相关扩展
- 对应 metadata 的清理

七、只做图片还不够,视频和 PDF 也得补
如果只做图片,这个工具依然不能算真正好用。因为现实使用里,视频和 PDF 也经常会出现在“需要去 metadata”的列表里。
MP4 / MOV / M4V
这一块我先做的是一个基础但实用的版本,重点是 QuickTime 容器里比较常见的几类 metadata:
moovudtametailstXMP_
对应地,鸿蒙侧能做的事情包括:
- 读取常见 QuickTime metadata
- 读取 XMP
- 清理常见容器 metadata 块
它还远没有达到 ExifTool 对视频容器那种很深的覆盖,但至少已经不是“视频文件导入后什么都干不了”。
PDF 这块我采取的是比较克制的做法。
没有直接上一个完整 PDF 对象重写器,而是先支持:
- 读取
Info字典中的常见字段AuthorCreatorTitle
- 识别 PDF 里的 XMP
- 清理 ExifTool 风格的 PDF 增量更新 metadata 段
这么做的原因很简单:当前项目里最常见、也最现实的 PDF 场景就是这类结构,先把它做稳,比一开始追求“大而全”更靠谱。

八、RAW 的第一步:先从 DNG 和 CR3 切进去
做完高频图片、视频和 PDF 之后,后面最有代表性的工作就是 RAW。
这一块如果想一步做到和 ExifTool 同等级,几乎不现实。因为 RAW 家族不是一个格式,而是一整个世界,每家厂商都有自己的私有结构和细节。
所以我的策略还是一样:先从最容易接进去、收益又足够高的点开始。
DNG
DNG 本质上还是 TIFF 体系,所以它是最适合作为 RAW 第一站的。
有了前面 TIFF 的基础以后,DNG 这一步比较顺:
- 读取 metadata
- 清理 metadata
- 复用 TIFF 里的 orientation / ICC / XMP 相关逻辑
CR3
CR3 则是另一种情况,它更接近 HEIF / AVIF 那条 ISO BMFF 容器路线。
所以这里我先做了一个基础版:
- 读取常见 EXIF metadata box
- 清理常见 metadata box
这还不能说已经完整支持 Canon RAW,但它至少把 CR3 从“完全不支持”推进到了“有基础处理能力”。
这一步完成以后,鸿蒙版的格式覆盖就开始有点体系化的味道了,而不是只靠几种常见图片撑场面。
九、这次适配里,我最在意的不是“支持了多少格式”,而是几件更底层的事
如果只看提交记录,这次工作像是在不停给 HarmonyMetadataAdapter 加格式支持。
但真正决定这次适配有没有价值的,其实是下面几件事。
1. 不再把鸿蒙适配建立在桌面运行时侥幸可用的前提上
这是最根本的一点。
如果底层还是强依赖桌面版 ExifTool,那所有适配都只是在修表层问题。看起来修好了,实际随时会被运行环境一刀切回原形。
2. 改动尽量集中在基础设施层,而不是把业务层打散
这次大部分能力接管,都尽量压在:
HarmonyMetadataAdapter- 资源路径解析
- 鸿蒙打包脚本
这样做的好处是,上层界面、主流程、IPC 调用不用被大面积重写,后续维护会轻很多。
3. 每补一种能力,都尽量带测试
这一点非常重要。
因为 metadata 处理不是一个“看起来能跑就算好了”的领域。很多时候代码能过编译,甚至文件也能导出,但读取出来的字段不对、偏移错了、清理后文件结构变了,这些问题如果没有测试,很容易越改越乱。
这次后面之所以能越改越快,和前面持续补 vitest 回归测试关系很大。

十、现在这个版本到底到了什么程度
做到这里,我觉得可以比较坦率地给一个判断。
已经做到的
当前鸿蒙版已经具备了下面这些基础:
- 应用可启动
- 主界面可正常显示
- 文件导入流程可跑通
- 文件大小等基础信息可展示
- 多类主流格式已经有真实 metadata 读取能力
- 多类主流格式已经有真实 metadata 清理能力
目前已经接入并经过回归测试验证的主要类型包括:
- 图片:
JPEG / PNG / GIF / WebP / HEIC / HEIF / AVIF / TIFF / DNG / CR3 - 视频容器:
MP4 / MOV / M4V - 文档:
PDF
十一、这次改造给我的一个很直接的感受
以前做跨平台适配时,我常常会先盯着“界面能不能起来”。这当然也重要,但这次把 ExifCleaner 改到鸿蒙上以后,我反而更确定了一件事:
很多 Electron 项目的真正门槛,不在 UI,而在桌面默认依赖的那堆底层能力。
桌面环境太“宽容”了,很多项目在 macOS、Windows、Linux 上跑久了,会自然默认:
- 路径就该这么写
- 进程就该这么起
- 资源就该在这个位置
- 外部工具就该随时能调用
一旦到了鸿蒙,这些默认前提会被一项一项拆掉。
从这个角度看,这次适配其实不是简单的“把项目搬过去”,而是在倒逼我重新理解这个项目到底靠什么活着。
ExifCleaner 表面上是一个 Electron 小工具,但它真正的核心能力并不在 React 组件里,而在 metadata 处理引擎里。把这个认清楚以后,后面的路就反而清楚了:
- 先接管能力入口
- 再覆盖高频格式
- 再往复杂格式递进
这条路线虽然不炫,但很稳。
十二、如果你也在做类似项目的鸿蒙适配,我会建议你优先做这几件事
最后给几个很实际的建议,都是这次改造里踩过坑之后留下来的。
1. 先搞清楚项目真正依赖的“桌面能力”是什么
别被 UI 迷惑。很多项目真正难适配的地方,都在进程、文件、资源、外部二进制、系统 API 这些地方。
2. 优先做一层平台适配,而不是全局到处写 if else
像这次的 HarmonyMetadataAdapter,虽然前期投入不小,但一旦立住,后续就会越来越顺。
3. 不要一开始就追求“全格式支持”
先把高频格式做稳,比一口气列一长串支持表有意义得多。
4. 资源路径问题要尽早统一
这个坑非常常见,而且会反复出现。越晚处理,后面越难查。
5. 测试一定要跟上
尤其是文件格式处理这种活,一旦没有测试,后面改一个格式很可能把另一个格式带坏。
十三、结语
回头看这次适配过程,我觉得它最有价值的地方,不是“最终支持了多少种格式”,而是把一件事情做实了:
鸿蒙版 ExifCleaner 不再只是一个界面能打开的壳,而是开始具备真正处理文件的能力。
这一步做出来之后,后面无论是继续补 RAW、补更深的视频 metadata,还是把 PDF 做得更完整,至少都已经站在一条可持续演进的路线上了。
如果把这次工作浓缩成一句话,我会这样概括:
鸿蒙适配最难的,从来不是把窗口拉起来,而是把桌面环境里那些理所当然的底层能力,重新在新平台上接回来。
更多推荐



所有评论(0)