简述PDF原理和实践

news2024/9/20 2:44:51

Hello,我是小恒不会java。
由于最近有输出PDF报表的项目需求,所以复习一下PDF到底是什么,该如何产生,如何应用至项目中。
更多参见Adobe官方文档(https://www.adobe.com/cn/)

PDF原理

PDFPortable Document Format,可移植文档格式)是一种用于可靠地呈现和交换文档的标准文件格式。它的设计目标是无论在何种操作系统、硬件配置、字体资源或软件环境下,都能精确地复现原始文档的外观和内容。

为了达到这个效果,我们需要控制每个字符、每个图形的位置。为此Adode的工程师设计了一种语言:PostScript

上经典代码

%PDF-1.1
%¥±ë

1 0 obj
  << /Type /Catalog
     /Pages 2 0 R
  >>
endobj

2 0 obj
  << /Type /Pages
     /Kids [3 0 R]
     /Count 1
     /MediaBox [0 0 300 144]
  >>
endobj

3 0 obj
  <<  /Type /Page
      /Parent 2 0 R
      /Resources
       << /Font
           << /F1
               << /Type /Font
                  /Subtype /Type1
                  /BaseFont /Times-Roman
               >>
           >>
       >>
      /Contents 4 0 R
  >>
endobj

4 0 obj
  << /Length 55 >>
stream
  BT
    /F1 18 Tf
    0 0 Td
    (Im liheng) Tj
  ET
endstream
endobj

xref
0 5
0000000000 65535 f
0000000018 00000 n
0000000077 00000 n
0000000178 00000 n
0000000457 00000 n
trailer
  <<  /Root 1 0 R
      /Size 5
  >>
startxref
565
%%EOF

在这里插入图片描述

%PDF-1.1:PDF文件的版本号,这里是1.1版本。
%¥±ë:PDF文件的二进制标识符,用于区分文本和二进制数据。
1 0 obj:第一个对象,类型为Catalog,包含文档的根对象。
2 0 obj:第二个对象,类型为Pages,包含文档的页面对象。
3 0 obj:第三个对象,类型为Page,包含单个页面的信息。
4 0 obj:第四个对象,类型为Contents,包含页面的内容流。
xref:交叉引用表,列出了PDF文件中每个对象的位置和状态。
trailer:文件尾部,包含文档的根对象和文件大小等信息。
startxref:交叉引用表的起始位置。
%%EOF:PDF文件的结束标记。
PDF文件由多个对象组成,每个对象都有一个唯一的对象编号和生成编号。对象之间通过引用关系连接。在这个示例中,Catalog对象引用了Pages对象,Pages对象引用了Page对象,Page对象引用了Contents对象。Contents对象包含了显示"Hello World"的内容流。
编程形式与页面描述
PDF是一种编程形式的文档格式,其内容通过一系列操作符(operators)进行描述,这些操作符按照特定语法组织,形成一种类似编程语言的指令集。每个PDF文件实质上是一个程序,当被PDF阅读器解析时,它会按照指令重新绘制文档的各个元素,从而在任何支持PDF的系统上一致地呈现文档。

基本结构与显示单元

基本显示单元

文字:文本内容以字符序列的形式存储,附带字体、大小、颜色、位置等属性信息。
图片:包括位图(如JPGPNG)和矢量图形(如线条、形状),以嵌入或链接的方式包含在文件中。
矢量图:使用数学公式描述的图形,可以无限放大而不失真,如线条、曲线、形状等。
页面:PDF文件的基本组织单位,每个页面包含其自身的尺寸、布局、背景、内容流等属性。

扩展单元

元数据:如标题、作者、创建日期等文档元信息。
交互对象:如超链接、按钮、表单域、多媒体内容(音频、视频)、3D模型等,提供了文档的交互功能。
安全特性:如数字签名、权限控制、加密保护等,确保文档的安全性和完整性。
导航元素:如书签、目录、超链接等,帮助用户在文档内快速定位和跳转。
文件结构

PDF文件遵循严格的内部结构,通常包括以下几个部分:

Header:包含PDF版本信息和其他全局设置。

Body:主体部分,由一系列对象(Object)组成,每个对象都有唯一的标识(Object Number和Generation
Number),并按照交叉引用表(Cross-Reference Table)组织,便于随机访问。

Catalog(根对象):指向文档的其他关键部分,如Pages树、Outlines(书签)、Metadata等。

Pages树:描述文档的层级结构,每个页面作为一个单独的对象,包含其内容流(Content Stream)和资源(如字体、图像)引用。

Content Streams:包含前面提到的操作符序列,定义页面上的具体内容绘制指令。

Resources:如字体描述、图像数据等,供内容流引用。

Cross-Reference Table(XREF):列出文件中所有对象的位置信息,使得阅读器能够快速定位到需要的对象。

Trailer:包含XREF表的位置、加密信息(如有)、文件的主目录(Root object)等元数据。 解析与渲染流程

PDF阅读器执行步骤

解析文件头:确认文件为PDF格式并识别其版本。

加载交叉引用表:利用XREF表快速查找文件中对象的位置。

解析对象:按需读取和解析对象(如Catalog、Pages树、Content Streams等),构建文档内部结构的逻辑视图。

渲染页面:对于每个页面,根据其内容流中的操作符序列,逐个绘制文字、图形、图像等元素,应用适当的样式和变换,最终形成可视化的页面图像。

处理交互功能:如果文档包含交互元素,如超链接、表单等,阅读器还需要实现相关的事件响应和用户交互支持。

Java

在Java项目中,有几个流行的库可以用来生成PDF文件,例如iText和Apache PDFBox。
使用iText库:
首先,将iText库添加到项目的依赖中。对于Maven项目,将以下依赖添加到pom.xml文件中:

   <groupId>com.itextpdf</groupId>
   <artifactId>itext7-core</artifactId>
   <version>7.1.16</version>
</dependency>

接下来,使用以下代码创建一个简单的PDF文件:


import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;

import java.io.File;
import java.io.IOException;

public class PdfExample {
    public static void main(String[] args) {
        try {
            // 创建PdfWriter实例
            PdfWriter writer = new PdfWriter(new File("hello_world.pdf"));

            // 创建PdfDocument实例
            PdfDocument pdf = new PdfDocument(writer);

            // 创建Document实例
            Document document = new Document(pdf);

            // 添加内容
            document.add(new Paragraph("Hello, World!"));

            // 关闭文档
            document.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Django

在Django项目中,可以使用reportlab库生成PDF文件
接下来,使用以下view.py代码创建一个简单的PDF文件:

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from io import BytesIO
from django.http import FileResponse

def some_view(request):
    # 创建一个文件类似的缓冲区来接收 PDF 数据
    buffer = BytesIO()

    # 创建 Canvas 对象
    p = canvas.Canvas(buffer, pagesize=letter)

    # 添加内容
    p.drawString(100, 750, "Hello, World!")

    # 关闭 PDF 对象
    p.showPage()
    p.save()

    # 将缓冲区的内容移动到文件响应对象中
    buffer.seek(0)
    return FileResponse(buffer, as_attachment=True, filename='hello_world.pdf')

首先创建了一个BytesIO缓冲区来接收PDF数据。创建了一个canvas.Canvas对象,并使用drawString方法添加了一些文本。最后将缓冲区的内容移动到FileResponse对象中,并将其作为响应返回。

具体阅读官方文档,我在此写大致方向,时间太晚了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1611991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux内核之文件系统访问:目录项、inode、物理磁盘访问关系(五十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

(数据结构代码,总结,自我思考)=> { return 个人学习笔记; } 【To be continued~】

俗话说 “学而不思则罔”&#xff0c;是时候复习和整理一下自己先前的学习历程了&#xff01; Chapter-One 《BinarySearch》 public static int binarySearch (int[] a, int target) {int i 0, j a.length - 1;while (i < j) {int m (i j) >>> 1; // 求中位…

小红书电商运营实战课,从0打造全程实操(65节视频课)

课程内容&#xff1a; 1.小红书的电商介绍 .mp4 2.小红书的开店流程,mp4 3.小红书店铺基础设置介绍 ,mp4 4.小红书店铺产品上架流程 .mp4 5.客服的聊天过程和子账号建立 .mp4 6.店铺营销工具使用和后台活动参加 .mp4 7.小红书产品上架以及拍单教程,mp4 8.小红书如何选品…

javaWeb项目-智慧餐厅点餐管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JavaScript Java…

UltraScale+的40G/50G Ethernet Subsystem IP核使用

文章目录 前言一、设计框图二、模块说明三、上板3.1、发送端3.1、接收端 四、总结 前言 上文介绍了10G/25G Ethernet Subsystem IP核使用&#xff0c;本文将在此基础上介绍40G/50G Ethernet Subsystem IP核的使用&#xff0c;总体区别不大。 一、设计框图 由于40G以太网需要…

Jetson nx 外接OLED屏幕

40 针 GPIO 引脚 GPIO引脚可以用作输入或输出端口&#xff0c;它们提供了一个数字电平以使用户在外界设备上进行控制或读取。Jetson TX2 NX共有198个GPIO引脚&#xff0c;分为三个不同的管脚组&#xff1a;J1、J21和J22。每个管脚组都具有数字输入/输出和PWM功能。 以下是 TX2…

获取AngusTester应用免费许可

第一步、进入晓蚕云官网私有化部署&#xff0c;滑动到底部下载与安装&#xff0c;点击获取许可。 第二步、在获取许可申请页面填写申请信息。 注意&#xff1a;MAC地址为您安装应用服务器对应MAC地址&#xff0c;MAC地址错误会导致安装失败。 在常见的操作系统中&#xff0c;查…

Error in render: TypeError: Cannot read properties of undefined (reading‘‘)

报错内容 报错解释&#xff1a;这个错误在渲染过程中尝试读取一个未定义&#xff08;undefined&#xff09;对象的某个属性时发生了TypeError。具体来说&#xff0c;是尝试读取一个值为undefined的对象的某个属性&#xff0c;但该属性不存在&#xff0c;因此无法读取。解决过程…

【面试经典 150 | 二叉搜索树】验证二叉搜索树

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;中序遍历方法二&#xff1a;递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及…

国产信创办公软件(流版式软件)厂家汇总以及国产信创外设汇总

国产信创办公软件&#xff08;流版式软件&#xff09;厂家汇总以及国产信创外设汇总。 国产信创办公软件&#xff08;流版式软件&#xff09;厂家汇总 在信创背景下&#xff0c;国内流版式软件的发展呈现出蓬勃的态势。信创&#xff0c;即信息技术应用创新产业&#xff0c;旨在…

【C++】日期类Date(详解)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 日期类 日期类实现地图 获取某年某月的天数&#xff1a;GetMonthDay 检查日期合法&#xff0c;构造函数&#xff0c;拷贝构造函数&#xff0c;赋值运算符重载及析构函数…

【Qt】探索Qt框架:跨平台GUI开发的利器

文章目录 1. Qt框架概述1.1. Qt框架的优点1.2. Qt框架支持的系统1.3. Qt开发环境 2. 搭建 Qt 开发环境2.1. Qt SDK 的下载和安装2.2. 新建项目: 3. Qt 框架内容简介总结 在当今软件开发领域&#xff0c;跨平台性和用户界面的友好性是至关重要的。而Qt框架作为一款跨平台的C图形…

<计算机网络自顶向下> TCP拥塞

目录 TCP拥塞控制机制 TCP拥塞感知 TCP速率控制方法 TCP拥塞控制和流量控制的联合动作 TCP拥塞控制策略 TCP吞吐量 TCP公平性 TCP拥塞控制机制 端到端的拥塞控制机制 路由器不向主机提供有关拥塞的反馈信息 路由器负担较轻 符合网络核心简单的TCP/IP架构原则 端系统根据自…

【github主页】优化简历

【github主页】优化简历 写在最前面一、新建秘密仓库二、插件卡片配置1、仓库状态统计2、Most used languages&#xff08;GitHub 常用语言统计&#xff09;使用细则 3、Visitor Badge&#xff08;GitHub 访客徽章&#xff09;4、社交统计5、打字特效6、省略展示小猫 &#x1f…

浅谈命理学的男女婚姻篇

对于中国人来说&#xff0c;八字预测已成为生活中不可缺少的组成部分&#xff0c;不懂八字预测&#xff0c;就不会真正了解中国的传统文化。八字预测经历几千年的风风雨雨&#xff0c;是一种古老的中国命理学&#xff0c;通过生辰八字的天干地支的组合&#xff0c;可以推测一个…

[阅读笔记21][RA-CM3]Retrieval-Augmented Multimodal Language Modeling

这篇论文是meta联合斯坦福在23年4月发表的论文&#xff0c;提出了一个使用外部知识检索增强的多模态模型。 这篇模型提出的RA-CM3模型是第一个能够检索并生成图像文本的多模态模型&#xff0c;在图像文本生成任务上优于现有的多模态模型&#xff0c;同时使用更少的训练量。 RA-…

模型 框架效应

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。部分真相不等于真相。 1 框架效应的应用 1.1 框架效应在营销策略上的应用 亚洲航空公司面临的挑战是如何在竞争激烈的航空市场中吸引更多的顾客&#xff0c;并提高机票的预订率。这家低成本航空公司…

2.Vue简介

Vue简介 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0c;V…

Scala的函数至简原则

对于scala语言来说&#xff0c;函数的至简原则是它的一大特色。下面让我们一起来看看分别有什么吧&#xff01; 函数至简原则&#xff1a;能省则省&#xff01; 初始函数 def test(name:String):String{return name }1、return可以省略&#xff0c;Scala会使用函数体的最后一…