IPTVnator 本地 XMLTV 文件作为 EPG 源:绝对路径、`file://` 与原生文件选择器全解析

发布时间:2026/9/17 18:15:22

IPTVnator 本地 XMLTV 文件作为 EPG 源:绝对路径、`file://` 与原生文件选择器全解析 IPTVnator 本地 XMLTV 文件作为 EPG 源绝对路径、file://与原生文件选择器全解析【免费下载链接】iptvnator:tv: Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup and more.项目地址: https://gitcode.com/GitHub_Trending/ip/iptvnator导读本文基于 IPTVnator 仓库的.changes/epg-local-xmltv-sources.md变更记录系统讲解新版 EPG电子节目指南源如何从只能填 URL扩展为本地 XMLTV 文件也可直接使用的完整能力包括支持的三种引用形式绝对路径、file://链接、原生文件选择器、接受的两种压缩格式.xml与.xml.gz、一次性的原生授权确认流程以及背后主进程授权器、路径归一化与 gzip 探测的源码级实现。读完本文你将掌握在 Settings → EPG 或播放列表的 EPG 列表中安全添加本地节目单文件的具体操作与底层原理。功能背景EPG 源不再必须是 URL在 IPTVnator 中EPG 数据源XMLTV 节目单以往通过 URL 方式接入用户要么提供一个远程http(s)地址要么依赖 M3U 播放列表头部声明的url-tvg属性。这一方式对本地已有节目单文件的场景并不友好——用户需要在本地起一个 HTTP 服务或者把文件上传到某处才能喂给播放器。本次变更类型feature影响区域epg亮点标注 Local XMLTV files as EPG sources解除了这一限制Settings → EPG 或播放列表的 EPG 列表都可以直接指向计算机上的 XMLTV 文件支持以下三种引用方式绝对路径例如/home/you/epg/guide.xmlPOSIX或C:\epg\guide.xml.gzWindowsfile://链接例如file:///home/you/epg/guide.xml新的文件夹按钮通过系统原生文件对话框直接选择文件。同时纯文本.xml与 gzip 压缩的.xml.gz两种格式都被支持手输的路径在被读取前会经过一次原生对话框确认设置页会明确列出可接受的格式示例。三种本地引用形式与两类压缩格式形式一绝对路径直接把文件系统的绝对路径粘贴进 EPG 源输入框即可。为了在不同平台上都能工作源码中的引用分类工具classifyEpgSourceReference支持三类本地绝对路径见 epg-source-reference.util.ts平台/类型匹配模式示例POSIX 绝对路径^\/[^\0]$/home/you/epg/guide.xmlWindows 盘符路径^[a-z]:[\\/][^\0]*$不区分大小写C:\epg\guide.xml.gzWindows UNC 路径^\\\\[^\\/\0]\\.\\NAS\epg\guide.xml值得注意的是相对路径如epg/guide.xml会被有意拒绝——主进程没有可解释的工作目录来解析相对路径因此只接受绝对形式见 epg-source-reference.util.ts 注释及对应的 epg-source-reference.util.spec.ts 测试。形式二file://链接file://URL 同样被识别为本地源与普通绝对路径在归一化后等价。在 epg-local-source-path.ts 中resolveLocalEpgSourcePath对file:前缀的值调用 Node.js 的fileURLToPath后再resolve对普通路径则要求isAbsolute通过后resolve。因此以下写法会归一化到同一个文件file:///home/you/epg/guide.xml/home/you/epg/guide.xml其单元测试明确断言maps a file URL and the plain path to the same normalized path见 epg-local-source-path.spec.ts同时验证了带空格的文件名guide v2.xml.gz与首尾空白也能正确处理。而https://…、相对路径、空字符串和裸file://则返回null表示不是本地文件引用。形式三原生文件选择器文件夹按钮在设置页 EPG 源列表的每一行新增了一个文件浏览按钮模板中为browseEpgSource输出见 settings-epg-section.component.html。点击后Angular 侧通过EpgRuntimeBridgeService.pickEpgFile()调用主进程的EPG_OPEN_FILE_DIALOGIPC见 settings-epg.facade.ts。主进程用 Electron 的dialog.showOpenDialog弹出原生对话框见 epg.events.ts文件过滤器如下dialog.showOpenDialog({ properties: [openFile], filters: [ { name: XMLTV, extensions: [xml, gz, xmltv] }, { name: All Files, extensions: [*] }, ], });可见除了.xml、.gz外.xmltv扩展名也被视为 XMLTV 文件类型用户取消时返回null设置行的值保持不变。选中的文件路径会立即通过授权器写入信任列表authorize保证后续刷新不再弹窗。格式与压缩.xml与.xml.gz均支持设置页会明确展示可接受的格式提示与示例。在 settings-epg-section.component.html 中data-test-idepg-source-formats区域呈现了四种示例https://example.org/guide.xml.gz /home/you/epg/guide.xml C:\epg\guide.xml.gz file:///…/guide.xml本地文件读取时gzip 解压不依赖扩展名而是通过文件自身的魔数magic signature探测。在 epg-source-stream.ts 的注释中明确说明gzip is detected from the files own signature, soguide.xml,guide.xml.gzand a gzip file without the extension all work——也就是说即使一个 gzip 文件没有.gz后缀只要内容确实是 gzip 压缩的 XMLTV也能被正确解压。手输路径的一次性原生确认授权模型本地文件读取最大的安全问题是如果渲染进程Renderer能把任意路径当作 EPG 源提交给主进程一个被攻破或恶意构造的页面就能让应用读取磁盘上任意文件。为此本次变更引入了一套主进程授权门禁与导出播放列表时save-file-dialog→write-file的安全模式一致见 epg-local-source-authorizer.ts 的注释。授权器接口与默认拒绝策略核心接口EpgLocalSourceAuthorizer定义了两个方法epg-local-source-authorizer.tsauthorize(filePath)用户在原生选择器中选中的文件立即信任无需弹窗ensureAllowed(filePath)判断路径是否可读手输路径首次触发一次原生确认弹窗。在 epg-worker.service.ts 中worker 服务初始化时挂载的是DENY_ALL_EPG_LOCAL_SOURCES拒绝一切本地文件直到epg.events.ts注册阶段才替换为真实的持久化授权器。这意味着任何未正确接线的情况都会失败关闭fail closed而不是放行。持久化与并发去重真实的实现是PersistedEpgLocalSourceAuthorizerepg-local-source-authorizer.ts允许列表持久化在主进程的配置存储中键为TRUSTED_LOCAL_EPG_SOURCES见 epg.events.ts因此应用启动时的自动刷新不再需要重新弹窗确认使用pendingPromptsMap 对同一文件并发请求例如设置页保存与启动刷新同时触发共享同一个弹窗避免堆叠多个对话框。原生确认对话框手输路径第一次读取时会弹出原生消息框epg-local-source-authorizer.ts标题Allow local EPG file?消息Read this file as an EPG source?详情展示完整路径并提示 IPTVnator will read the XMLTV guide data in this file. Only allow files you added yourself.按钮Allow默认/Cancel取消对话框通过BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0]挂到当前窗口。若用户拒绝worker 会返回固定的错误文案Reading this local file was not allowed. Retry to be asked again.EPG_LOCAL_SOURCE_REFUSED_MESSAGEepg-local-source-authorizer.ts并把该次抓取标记为失败——拒绝视为未读取不能伪装成已完成的抓取。渲染进程旗标被剥离防止越权在 epg-worker.service.ts 的startFetch中有两道关键防线从渲染进程传来的allowLocalFile旗标被显式解构剥离const { allowLocalFile: _rendererFlag, ...trustOptions } options渲染进程无法用它解锁本地分支只有resolveLocalEpgSourcePath判定为本地路径、且ensureAllowed返回true之后worker 才会构造{ ...trustOptions, allowLocalFile: true }并交给底层抓取逻辑。openEpgSourceStream端还有兜底校验epg-source-stream.ts即便走到了本地分支若allowLocalFile ! true也会抛错Local EPG file was not authorized。读取与解码流水线从路径到节目单数据EPG 抓取统一由openEpgSourceStream入口分流epg-source-stream.ts本地引用走磁盘读取其余走经过校验的远程 HTTP 客户端。本地分支async function openLocalEpgSource(filePath: string): PromiseReadable { const info await stat(filePath); // 不存在则抛 EPG file not found if (!info.isFile()) { // 目录则抛 EPG source is not a file throw new Error(EPG source is not a file: ${filePath}); } pipeline( createReadStream(filePath), // 流式读取避免整文件驻留内存 createOptionalEpgGunzip(), // 依据文件魔数自动探测 gzip output, (error) { if (error) output.destroy(error); } ); return output; }关键点epg-source-stream.ts先stat校验存在性与是文件而非目录ENOENT/ENOTDIR会给出友好错误使用createReadStream流式读取经createOptionalEpgGunzip()后送入PassThrough后续的流式 XML 解析器可以直接消费大节目单文件也不会一次性载入内存gzip 探测依据的是文件签名而非扩展名。远程分支对比远程源走requestWithValidatedRedirects每个重定向都被校验且访问私网/局域网源需要操作者显式开启信任isPrivateNetworkUrlAccessAllowed()或该 URL 在trustedPrivateNetworkEpgUrls白名单中见 epg-source-stream.ts。响应还会依据Content-Encoding与 URL/文件名判断是否需要 gunzip。两分支最终都产出已解码的 XMLTV 字节流交给共享的流式解析器。M3U 头部 URL 与本地文件的安全边界本地源只可能来自用户手工输入Settings → EPG、播放列表对话框。从 M3U 头部url-tvg属性提取的 EPG URL 在入库前会被过滤为仅远程链接extractM3uEpgUrls因此下载一个播放列表永远不会把 EPG 导入器指向用户磁盘上的任意文件见 epg-source-stream.ts 与 epg-source-reference.util.ts 注释。表单校验设置页与播放列表对话框共用同一套规则本地源在表单层就做了前置校验。validateEpgSourceReferenceControl作为无 Angular 依赖的结构化校验器epg-source-reference.util.ts被 Settings 的 EPG 列表和播放列表 EPG 对话框共用空值合法与Validators.pattern行为一致允许用户留空非空值必须能通过classifyEpgSourceReference分类remote或local否则返回epgSourceReference校验错误。这意味着用户在保存前就能发现相对路径/非法字符串问题而不是等到抓取阶段才报错。刷新与新鲜度本地文件同样遵守 12 小时阈值本地文件源与远程源共享同一套抓取编排handleFetchEpg见 epg-fetch.service.tsEPG_FRESHNESS_MAX_AGE_HOURS 12存储的 EPG 数据超过 12 小时即视为过期需要重新抓取每个源按sourceUrl对本地文件就是归一化后的绝对路径记录updatedAtcheckEpgFreshness据此区分freshUrls与staleUrls多个 URL顺序抓取避免 SQLite 数据库锁冲突抓取进度通过sendProgressToRenderer推送queued/loading/…等状态手动刷新按钮走EPG_FORCE_FETCH先删除已抓取标记再强制抓取绕过 12 小时阈值。由于信任列表已持久化应用重启后的启动刷新对已授权文件不会再次弹窗用户几乎无感。源码速览本次特性的关键文件关注点文件变更记录.changes/epg-local-xmltv-sources.md引用分类与表单校验libs/shared/interfaces/src/lib/epg-source-reference.util.ts、epg-source-reference.util.spec.ts路径归一化file:/绝对路径apps/electron-backend/src/app/util/epg-local-source-path.ts、epg-local-source-path.spec.ts主进程授权器与原生确认框apps/electron-backend/src/app/events/epg-local-source-authorizer.tsIPC 注册与原生文件选择器apps/electron-backend/src/app/events/epg.events.tsWorker 侧授权门禁与旗标剥离apps/electron-backend/src/app/events/epg-worker.service.ts本地/远程流打开与 gzip 探测apps/electron-backend/src/app/workers/epg-source-stream.ts抓取编排与新鲜度阈值apps/electron-backend/src/app/events/epg-fetch.service.ts设置页 UI格式提示示例apps/web/src/app/settings/settings-epg-section.component.html设置页浏览动作browseapps/web/src/app/settings/settings-epg.facade.ts使用小结在 IPTVnatorElectron 桌面端中接入本地 XMLTV 节目单按如下步骤即可打开Settings → EPG或进入某个播放列表的EPG 列表在 EPG 源输入框中粘贴绝对路径/home/you/epg/guide.xml、C:\epg\guide.xml.gz或file://链接也可以点击文件夹按钮通过原生对话框选择支持.xml、.gz、.xmltv若为手输路径首次保存/刷新时会弹出一次原生确认框选择Allow后即可读取后续不再询问文件格式支持纯文本.xml与 gzip 压缩的.xml.gz解压依据文件签名自动判断与扩展名无关之后与远程源一样受 12 小时新鲜度机制管理可手动强制刷新。这套实现的价值在于在不牺牲安全性的前提下主进程授权、默认拒绝、渲染进程旗标剥离、M3U 头部过滤把 EPG 数据源从必须联网扩展到本地离线文件让没有互联网环境或已有现成 XMLTV 文件的用户能够直接利用本地节目单数据。【免费下载链接】iptvnator:tv: Cross-platform IPTV player application with multiple features, such as support of m3u and m3u8 playlists, favorites, TV guide, TV archive/catchup and more.项目地址: https://gitcode.com/GitHub_Trending/ip/iptvnator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/17 18:10:21

HCIA-Datacom实战:数据封装、VLAN与NAT配置详解

简介:HCIA-Datacom核心技术笔记总结是一份面向网络工程师、网络管理员、学生及企业IT人员的系统学习资料,针对网络协议理解不深、配置经验不足等常见痛点。笔记以清晰的章节结构从网络基础讲起,依次涵盖数据封装、OSI与TCP/IP模型、Wireshark…

2026/9/17 18:10:21

从SNMP到NetFlow:构建可落地的监控采集链路

简介:以信息技术运维管理基础知识为主题的幻灯片学习教案,面向运维入门者、技术培训讲师和希望系统梳理运维知识的学习者。内容围绕监控软件与采集协议展开,涵盖SNMP、RMON、Syslog、Telnet/SSH、ODBC/JDBC、WMI等十余种常用协议,…

2026/9/17 18:10:21

Copilot替代方案本质是开发范式迁移:从补全到Agent

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 19:20:28

Rerun 实战:使用 NV12 像素格式流式显示摄像头视频

Rerun 实战:使用 NV12 像素格式流式显示摄像头视频 【免费下载链接】rerun Visualize, query, and stream to train on multimodal robotics data. 项目地址: https://gitcode.com/GitHub_Trending/re/rerun 本篇技术指南围绕 Rerun 官方示例 examples/python…

2026/9/17 19:20:28

Folo智能翻译:打破语言壁垒的利器

Folo智能翻译:打破语言壁垒的利器 在这个信息爆炸的时代,我们每天都会接触到来自世界各地的内容。语言的差异常常成为我们获取知识的障碍。Folo的智能翻译功能正是为解决这一痛点而生,让你轻松跨越语言鸿沟,畅游全球资讯海洋。 …

2026/9/17 19:20:28

电力监控网络安全方案:白名单与隔离装置落地实践

简介:这是一份面向电力监控系统网络安全建设的完整方案文档,适合电力行业运维、安全及设计人员参考使用。文档从背景意义与现状分析入手,先梳理电力监控系统组成、运行环境与安全短板,再围绕网络安全目标与原则,展开物…

2026/9/17 19:20:28

Arduino零基础入门:从开箱到工业级项目的硬核实操路径

1. 这不是“学完就能做项目”的速成课,而是帮你把Arduino真正焊进肌肉记忆的实操路径你搜“Arduino零基础入门”,页面刷出来几百个标题带“保姆级”“全套”“从0到1”的视频合集——点开前3秒,画面是整齐的开发板特写激昂BGM,讲师…

2026/9/17 19:15:28

EGM2008高程转换:单水准点实现厘米级GPS高程精度

简介:本资源是一份面向测绘、GIS及地理信息工程领域从业者与高校相关专业师生的专业技术文献,聚焦GPS高程转换这一实际工程难点,提出基于EGM2008全球重力场模型的高效解决方案。针对山区等水准点稀少区域难以实施传统曲面拟合法的问题&#x…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码