1

我正在尝试以编程方式生成 PDF 文件。

整个案例是:我收到一个多页 PDFS。每个页面都是一个图像,包含我想要的内容。我不想使用外部库,因为我正在寻找性能\优化(从长远来看,这对我很重要)。我曾经有一些已经在工作的东西(我创建了一个像 header\file content(image)\footer 这样的系统),而且它一直都在工作。但是,有些事情发生了变化,它停止了工作。

无论如何,为了修复它并从头开始构建,这是我执行的步骤:

  1. 提取与图像文件相关的 FlateDecode 部分(众多之一)
  2. 从中创建了一个干净的 JPEG(没有 Photoshop 标题等,一个简单的 JPEG 文件)
  3. 将文件提交给一些在线PDF转换服务;从此 JPEG 创建了一个文件。
  4. 确定 PDF 文件的构建方式和图像部分。手动编码所有内容,包括外部参照表中的引用
  5. 我得到的只是“文件已损坏”。我比较了这两个文件(原始文件和我制作的文件),它们似乎几乎相等(由于图像部分的大小差异)。

我不知道还能做什么,因为一切似乎都非常完美。我还解码了 PDF 文件中的一些字符串 FlateDecode 部分,但我在文件中找不到与对象定位相关的任何内容。

这是我正在使用的代码:

using (var b = new BinaryWriter(File.Open(@"C:\test\Rio\Reboot\fullmanual01.pdf", FileMode.Create)))
{
    var imgBytes = File.ReadAllBytes(@"C:\test\Rio\Reboot\decompressedimg.raw");
    var firstFlate = File.ReadAllBytes(@"C:\test\Rio\Reboot\flateStr01.raw");
    var FlateDecompressed = Encoding.ASCII.GetString(FlateDecompress(firstFlate));
    string crlf = Environment.NewLine;

    var pdfHeader = Encoding.ASCII.GetBytes($"%PDF-1.4{crlf}");
    b.Write(pdfHeader);
    pdfHeader = StringToByteArray("25E2E3CFD30D0A");
    b.Write(pdfHeader);
    var pdfObj = new PDFStrObject(1, $"/Type /Page{crlf}/MediaBox [ 0 0 595 769 ]{crlf}/Resources << /XObject << /X0 3 0 R >> >>{crlf}/Contents 4 0{crlf}/Parent 2 0 R{crlf}/Rotate 360{crlf}>>{crlf}endobj{crlf}").byteFromStrObj;
    b.Write(pdfObj);
    var secondObjPos = b.BaseStream.Position.ToString("0000000000");
    pdfObj = new PDFStrObject(3, $"/Type /XObject{crlf}/Subtype /Image{crlf}/Width 1016{crlf}/Height 1328{crlf}/BitsPerComponent 8{crlf}/ColorSpace /DeviceGray{crlf}/Filter /FlateDecode{crlf}/Length {imgBytes.Length}{crlf}>>{crlf}stream{crlf}").byteFromStrObj;
    b.Write(pdfObj);
    b.Write(imgBytes);
    b.Write(Encoding.ASCII.GetBytes($"{crlf}endstream{crlf}endobj{crlf}"));
    var thirdObjPos = b.BaseStream.Position.ToString("0000000000");
    pdfObj = new PDFStrObject(4, $"/Filter /FlateDecode{crlf}/Length 45{crlf}>>{crlf}stream{crlf}").byteFromStrObj;
    b.Write(pdfObj);
    b.Write(firstFlate);
    b.Write(Encoding.ASCII.GetBytes($"{crlf}endstream{crlf}endobj{crlf}"));
    var secondPos = b.BaseStream.Position;
    pdfObj = new PDFStrObject(2, $"/Type /Pages{crlf}/Kids [ 1 0 R ]{crlf}/Count 1{crlf}>>{crlf}endobj{crlf}").byteFromStrObj;
    b.Write(pdfObj);
    var firstObjPos = b.BaseStream.Position.ToString("0000000000"); //2 0 obj
    pdfObj = new PDFStrObject(5, $"/Type /Catalog{crlf}/Pages 2 0{crlf}>>{crlf}endobj{crlf}").byteFromStrObj;
    b.Write(pdfObj);
    var fourthObhPos = b.BaseStream.Position.ToString("0000000000");
    b.Write(Encoding.ASCII.GetBytes($"xref{crlf}0 6{crlf}"));
    b.Write(Encoding.ASCII.GetBytes($"0000000000 65535 f{crlf}0000000017 00000 n{crlf}"));

    b.Write(Encoding.ASCII.GetBytes($"{firstObjPos} 00000 n{crlf}"));

    b.Write(Encoding.ASCII.GetBytes($"{secondObjPos} 00000 n{crlf}"));

    b.Write(Encoding.ASCII.GetBytes($"{thirdObjPos} 00000 n{crlf}"));
    b.Write(Encoding.ASCII.GetBytes($"{fourthObhPos} 00000 n{crlf}"));
    b.Write(Encoding.ASCII.GetBytes($"trailer{crlf}<<{crlf}/Size 6{crlf}/Root 5 0{crlf}/ID [<05bebfaf5c6382cfbc44cd1b3389e097><05bebfaf5c6382cfbc44cd1b3389e097>]{crlf}>>{crlf}startxref{crlf}{b.BaseStream.Position+7}{crlf}%%EOF{crlf}"));
}

以及用于构建对象的类:

class PDFStrObject
{
    public string strObj { get; private set; }
    public byte[] byteFromStrObj { get; private set; }
    public PDFStrObject(int objNum, string content)
    {
        string crlf = Environment.NewLine;

        strObj =  $"{objNum} 0 obj{crlf}<<{crlf}{content}";
        byteFromStrObj = Encoding.ASCII.GetBytes(strObj);
    }
}

我一直在使用的文件在这里:https ://drive.google.com/drive/folders/11HN9cB9Cs7uqBQdpZkNyNKt29sl_xJrL?usp=sharing

描述是:

decompressedimg-convertido.pdf -> 我在线转换的文件。

decompressedimg.raw -> 我从多页 PDF 中提取的图像部分。尺寸为W:1016,H:1328

fullmanual01.pdf -> 我使用我的代码生成的文件。

PDfRjMultiplePages -> 包含多个页面的 PDF 文件,我愿意以编程方式从中提取页面。

任何输入表示赞赏。我还提到了这个问题:从头开始编写 PDF 文件的问题,但找不到我正在尝试做什么的提示(不幸的是)

坦克

4

1 回答 1

3

突出的第一件事是您startxref指向错误的位置。

在此处输入图像描述

它指向红色,但应该指向蓝色点。

另一个明显的问题是文件中间有一个较早的外部参照表。因此,您要么尝试(可能是无意中)创建线性化或增量 PDF 文件。根据您的描述,这两种做法都没有意义。你应该坚持使用基本的 PDF,文件末尾有一个外部参照表。

您应该仔细查看您引用的那篇文章,这似乎是一个很好的起点。

PDF 1.7 规范还提供了非常简单的示例。

很可能还有其他问题。您可能需要重新考虑使用第 3 方库来创建您的 PDF 文件。

于 2020-01-30T05:37:25.403 回答