在 Rust 中修复损坏的 PDF — 从头重建 XREF 表

发布: (2026年4月28日 GMT+8 10:34)
3 分钟阅读
原文: Dev.to

Source: Dev.to

问题

有些 PDF 无法打开,并不是因为内容缺失,而是因为指示阅读器在哪里找到内容的索引损坏了。
这个索引就是 XREF 表,它可以被重新构建。

XREF 表的样子

xref
0 6
0000000000 65535 f
0000000009 00000 n
0000000058 00000 n
0000000115 00000 n
0000000266 00000 n
0000000496 00000 n

当阅读器打开 PDF 时,会首先读取这个表。如果它缺失或损坏,PDF “无法打开”。内容对象仍然在文件中;我们只需要定位它们并重建索引。

在 Rust 中重建 XREF 表

pub fn rebuild_xref(data: &[u8]) -> Result {
    // lopdf can attempt recovery on malformed files
    let doc = Document::load_mem(data)
        .or_else(|_| recover_document(data))?;
    Ok(doc)
}

扫描对象

pub fn recover_document(data: &[u8]) -> Result {
    // Scan the raw bytes for object markers
    // Pattern: "N 0 obj" where N is the object number
    let mut offsets: Vec = Vec::new();
    let obj_pattern = b" 0 obj";

    for (i, window) in data.windows(obj_pattern.len()).enumerate() {
        if window == obj_pattern {
            // Walk back to find the object number
            if let Some(num) = extract_obj_num(data, i) {
                offsets.push((num, 0, i - num.to_string().len()));
            }
        }
    }

    // Reconstruct document from found objects
    rebuild_from_offsets(data, offsets)
}

重建有帮助的典型场景

  • PDF 在写入过程中被截断(例如,保存时断电)
  • PDF 进行增量更新后导致 XREF 链断裂
  • 老文件的 XREF 被手动错误编辑过
  • 扫描仪输出的结构异常的 PDF

如果内容流本身已损坏——实际页面数据丢失——则任何 XREF 重建都无济于事。结构性的复原仅在对象仍在但索引损坏时有效。

大约 80 % 的“无法打开”PDF 我测试过都是 XREF 问题。内容本身是完整的,只需要一个新的索引。

资源

0 浏览
Back to Blog

相关文章

阅读更多 »