Rust PDF处理库pdf的使用:高效解析、生成和操作PDF文档的Rust插件库

Rust PDF处理库pdf的使用:高效解析、生成和操作PDF文档的Rust插件库

pdf-rs是一个用于读取、修改和写入PDF文件的Rust库。

test clippy&fmt

功能特点

  • 读取、修改和写入PDF文件
  • 修改和写入PDF功能仍处于实验阶段
  • 可以通过添加不同PDF文件到tests/files目录来贡献测试用例

工作空间

该仓库使用Cargo Workspace,默认只构建pdf库。要构建其他部分,可以传递--package=read参数来构建你感兴趣的子crate。

示例

示例位于pdf/examples/目录,可以通过以下命令运行:

cargo run --example {content,metadata,names,read,text} -- <files/{选择PDF文件}>

渲染器和查看器

一个通过Pathfinder渲染PDF的库和最小化查看器

检查工具

有一个可视化PDF文件的工具,可以交互式地查看PDF原始结构。

完整示例代码

下面是一个使用pdf-rs读取PDF文件并提取文本内容的完整示例:

use pdf::file::File;
use pdf::object::*;
use pdf::error::PdfError;

fn main() -> Result<(), PdfError> {
    // 打开PDF文件
    let file = File::open("example.pdf")?;
    
    // 获取PDF文档
    let doc = file.get_root()?;
    
    // 遍历所有页面
    for (page_num, page) in doc.pages().enumerate() {
        println!("Page {}", page_num + 1);
        
        // 获取页面内容
        if let Some(content) = &page.contents {
            // 处理页面内容流
            for content in content {
                let content = content.decode()?;
                // 这里可以解析内容流获取文本和其他元素
                println!("Content stream length: {}", content.len());
            }
        }
    }
    
    Ok(())
}

另一个生成简单PDF的示例:

use pdf::*;
use pdf::object::*;
use pdf::build::*;

fn main() -> Result<(), PdfError> {
    // 创建新的PDF文档
    let mut doc = Document::empty();
    
    // 创建页面
    let mut page = PageBuilder::new(&doc);
    
    // 添加文本到页面
    page = page
        .begin_text()
        .set_font("F1", 12.0)
        .set_text_position(100.0, 700.0)
        .show_text("Hello, PDF-rs!")
        .end_text();
    
    // 添加页面到文档
    doc.push_page(page)?;
    
    // 保存PDF文件
    std::fs::write("output.pdf", doc.save_to()?)?;
    
    Ok(())
}

完整示例demo

PDF读取与内容提取示例

use pdf::file::File;
use pdf::object::*;
use pdf::error::PdfError;

// 主函数返回PdfError结果
fn main() -> Result<(), PdfError> {
    // 打开PDF文件
    let file = File::open("example.pdf")?;
    
    // 获取PDF文档根对象
    let doc = file.get_root()?;
    
    // 遍历所有页面
    for (page_num, page) in doc.pages().enumerate() {
        println!("正在处理第 {} 页", page_num + 1);
        
        // 检查并处理页面内容
        if let Some(content) = &page.contents {
            // 解码每个内容流
            for stream in content {
                let decoded = stream.decode()?;
                // 这里可以添加更复杂的内容解析逻辑
                println!("内容流大小: {} 字节", decoded.len());
                
                // 简单文本提取示例
                if let Ok(text) = String::from_utf8(decoded.to_vec()) {
                    println!("提取到的文本内容:\n{}", text);
                }
            }
        }
    }
    
    Ok(())
}

PDF生成与内容写入示例

use pdf::*;
use pdf::object::*;
use pdf::build::*;

fn main() -> Result<(), PdfError> {
    // 创建空白PDF文档
    let mut doc = Document::empty();
    
    // 添加字体资源
    let font = doc.add_object(IndirectObject::new(SimpleFont {
        base: BaseFont {
            name: "F1".into(),
            encoding: Some(Encoding::Standard),
            ..BaseFont::default()
        },
        ..SimpleFont::default()
    }));
    
    // 创建页面构建器
    let mut page = PageBuilder::new(&doc);
    
    // 设置页面内容
    page = page
        .begin_text()
        .set_font("F1", 24.0)  // 使用24pt字体
        .set_text_position(100.0, 700.0)  // 设置文本位置
        .show_text("Rust PDF生成示例")  // 第一行文本
        .move_text_position(0.0, -30.0)  // 下移30单位
        .show_text("使用pdf-rs库创建")  // 第二行文本
        .end_text();
    
    // 添加页面到文档
    doc.push_page(page)?;
    
    // 保存PDF文件
    std::fs::write("generated.pdf", doc.save_to()?)?;
    println!("PDF文件已成功生成!");
    
    Ok(())
}

安装

在项目目录中运行以下Cargo命令:

cargo add pdf

或在Cargo.toml中添加:

pdf = "0.9.0"

许可证

MIT许可证


1 回复

Rust PDF处理库pdf的使用指南

概述

pdf是一个纯Rust实现的PDF处理库,提供了高效解析、生成和操作PDF文档的功能。它支持读取现有PDF文件、创建新PDF文件以及修改PDF内容。

主要功能

  • 解析现有PDF文档
  • 创建新的PDF文档
  • 修改PDF内容
  • 提取文本和图像
  • 添加注释和水印
  • 合并/拆分PDF文档

安装方法

在Cargo.toml中添加依赖:

[dependencies]
pdf = "0.8.0"

基本使用方法

1. 读取PDF文档

use pdf::file::File;

fn main() -> Result<(), pdf::error::PdfError> {
    // 打开PDF文件
    let file = File::open("example.pdf")?;
    
    // 获取文档版本
    println!("PDF版本: {:?}", file.version());
    
    // 遍历所有页面
    for page in file.pages() {
        let page = page?;
        println!("页面尺寸: {:?}", page.media_box());
    }
    
    Ok(())
}

2. 创建新PDF文档

use pdf::{PdfWriter, Page, Rect, Mm};
use pdf::font::Font;
use pdf::encoder::Text;

fn main() -> Result<(), pdf::error::PdfError> {
    // 创建新的PDF写入器
    let mut writer = PdfWriter::new();
    
    // 添加一个页面
    let mut page = Page::new(Rect::new(Mm(0.0), Mm(0.0), Mm(210.0), Mm(297.0)));
    
    // 获取默认字体
    let font = Font::helvetica();
    
    // 添加文本到页面
    page.add_text(
        Text::new("Hello, PDF World!", font)
            .at(Mm(50.0), Mm(150.0))
            .size(24.0),
    );
    
    // 将页面添加到文档
    writer.add_page(page);
    
    // 保存到文件
    writer.write_to_file("output.pdf")?;
    
    Ok(())
}

3. 提取PDF文本内容

use pdf::file::File;
use pdf::object::*;

fn main() -> Result<(), pdf::error::PdfError> {
    let file = File::open("example.pdf")?;
    
    for (i, page) in file.pages().enumerate() {
        let page = page?;
        println!("--- 第 {} 页 ---", i + 1);
        
        if let Some(content) = page.content() {
            for operation in content.operations.iter() {
                if let Ok(op) = operation {
                    if let Operation::ShowText(text) = op {
                        println!("{}", text);
                    }
                }
            }
        }
    }
    
    Ok(())
}

4. 合并PDF文档

use pdf::{PdfWriter, Page};
use pdf::file::File;

fn merge_pdfs(filenames: &[&str], output: &str) -> Result<(), pdf::error::PdfError> {
    let mut writer = PdfWriter::new();
    
    for filename in filenames {
        let file = File::open(filename)?;
        
        for page in file.pages() {
            let page = page?;
            let mut new_page = Page::new(page.media_box().unwrap());
            // 这里需要更复杂的逻辑来复制页面内容
            // 实际应用中可能需要使用更高级的合并方法
            writer.add_page(new_page);
        }
    }
    
    writer.write_to_file(output)?;
    Ok(())
}

fn main() -> Result<(), pdf::error::PdfError> {
    merge_pdfs(&["doc1.pdf", "doc2.pdf"], "merged.pdf")
}

高级功能

添加水印

use pdf::{PdfWriter, Page, Rect, Mm};
use pdf::font::Font;
use pdf::encoder::{Text, Color};

fn add_watermark(input: &str, output: &str) -> Result<(), pdf::error::PdfError> {
    let file = File::open(input)?;
    let mut writer = PdfWriter::new();
    let font = Font::helvetica();
    
    for page in file.pages() {
        let original_page = page?;
        let mut new_page = Page::new(original_page.media_box().unwrap());
        
        // 复制原始页面内容
        // 这里简化处理,实际需要更复杂的逻辑
        
        // 添加水印文本
        new_page.add_text(
            Text::new("CONFIDENTIAL", font)
                .at(Mm(50.0), Mm(150.0))
                .size(48.0)
                .color(Color::Rgb(255, 0, 0))
                .rotate(45.0)
                .opacity(0.3),
        );
        
        writer.add_page(new_page);
    }
    
    writer.write_to_file(output)?;
    Ok(())
}

完整示例demo

下面是一个完整的PDF处理示例,展示了如何创建一个PDF文档并添加水印:

use pdf::{PdfWriter, Page, Rect, Mm};
use pdf::font::Font;
use pdf::encoder::{Text, Color};
use pdf::file::File;

fn main() -> Result<(), pdf::error::PdfError> {
    // 1. 创建一个新的PDF文档
    let mut writer = PdfWriter::new();
    
    // 2. 添加一个A4尺寸的页面
    let mut page = Page::new(Rect::new(Mm(0.0), Mm(0.0), Mm(210.0), Mm(297.0)));
    
    // 3. 获取Helvetica字体
    let font = Font::helvetica();
    
    // 4. 添加主文本内容
    page.add_text(
        Text::new("Rust PDF处理示例", font)
            .at(Mm(50.0), Mm(250.0))
            .size(36.0)
            .color(Color::Rgb(0, 0, 0)),
    );
    
    // 5. 添加副文本
    page.add_text(
        Text::new("使用pdf库创建PDF文档", font)
            .at(Mm(50.0), Mm(220.0))
            .size(24.0)
            .color(Color::Rgb(0, 0, 0)),
    );
    
    // 6. 将页面添加到文档
    writer.add_page(page);
    
    // 7. 保存初始文档
    writer.write_to_file("initial.pdf")?;
    
    // 8. 为文档添加水印
    add_watermark("initial.pdf", "watermarked.pdf")?;
    
    Ok(())
}

fn add_watermark(input: &str, output: &str) -> Result<(), pdf::error::PdfError> {
    let file = File::open(input)?;
    let mut writer = PdfWriter::new();
    let font = Font::helvetica();
    
    for page in file.pages() {
        let original_page = page?;
        let mut new_page = Page::new(original_page.media_box().unwrap());
        
        // 复制原始页面内容
        // 这里简化处理,实际需要更复杂的逻辑
        
        // 添加水印文本
        new_page.add_text(
            Text::new("示例水印", font)
                .at(Mm(50.0), Mm(150.0))
                .size(48.0)
                .color(Color::Rgb(255, 0, 0))
                .rotate(45.0)
                .opacity(0.3),
        );
        
        writer.add_page(new_page);
    }
    
    writer.write_to_file(output)?;
    Ok(())
}

注意事项

  1. 该库仍在积极开发中,某些高级PDF功能可能不完全支持
  2. 处理大型PDF文件时注意内存使用
  3. 复杂的PDF操作可能需要深入理解PDF格式规范
  4. 对于生产环境使用,建议充分测试所有功能

替代方案

如果需要更高级或更稳定的PDF功能,可以考虑以下替代方案:

  • lopdf - 另一个Rust PDF操作库
  • printpdf - 专注于PDF生成的库
  • 通过FFI绑定使用成熟的C/C++库如poppler或pdfium
回到顶部