You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PyMuPDF实现可点击打开的嵌入PDF引用功能?

用PyMuPDF实现带可点击嵌入文件的PDF合并

要实现类似LaTeX navigator包\openfilelink{}{}的效果,需要两步:先把文件嵌入主PDF,再在主文档中添加可点击的链接触发打开嵌入文件的动作。下面是完整实现方案:

文件结构示例

main_directory/
├── master.pdf
├── embedded_file1.pdf
└── embedded_file2.pdf

完整实现代码

import fitz
import os

def add_embedded_files_with_links(src: str, *files_to_embed: str) -> fitz.Document:
    doc = fitz.open(src)
    # 嵌入文件并记录文件名映射
    embedded_names = []
    embed_name_template = f"{{}}_EMBEDDED_IN_{os.path.basename(src)}"
    
    for f in files_to_embed:
        embed_name = embed_name_template.format(os.path.basename(f))
        embedded_names.append((os.path.basename(f), embed_name))
        
        with fitz.open(f) as embed_doc:
            embed_data = embed_doc.tobytes()
            doc.embfile_add(embed_name, embed_data)
    
    # 在主文档第一页添加可点击链接(可按需调整位置和目标页面)
    page = doc[0]
    y_pos = 50  # 链接起始Y坐标,可自行修改
    for display_name, embed_name in embedded_names:
        # 插入提示文本
        text_rect = page.insert_text((50, y_pos), f"打开{display_name}", fontsize=12)
        # 创建打开嵌入文件的动作
        action = fitz.PDFActionLaunch(embedded=embed_name)
        # 给文本区域绑定链接动作
        page.add_link(text_rect, action=action)
        y_pos += 30  # 下移下一个链接的位置
    
    return doc

# 配置路径
path_master_pdf = "master.pdf"
paths_files_to_embed = ["embedded_file1.pdf", "embedded_file2.pdf"]

# 生成最终PDF
output_path = path_master_pdf.removesuffix('.pdf') + '_with_embeddings.pdf'

with add_embedded_files_with_links(path_master_pdf, *paths_files_to_embed) as doc:
    doc.save(output_path)

关键说明

  1. 文件嵌入:通过embfile_add将待嵌入PDF的字节数据存入主文档,自定义嵌入文件名避免冲突。
  2. 可点击链接实现:
    • 在目标页面插入提示文本,获取文本对应的矩形区域
    • 创建PDFActionLaunch动作,指定embedded参数为嵌入的文件名
    • 用add_link把动作绑定到文本区域,点击后直接打开嵌入的PDF
  3. 自定义调整:可以修改链接的位置、目标页面、文本样式,也可以将链接绑定到图片或特定矩形区域,而非文本。

内容的提问来源于stack exchange,提问作者cards

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:52:16