围绕SO我已经看到了以下问题: Create Multi-Page PDF from other PDFs
但是它没有回答我的需要。 考虑我有一个20页的PDF。到目前为止一切顺利。
在同一地方,我只能拥有一页的PDF。这将用作我的模板PDF。 我想做的是替换模板PDF上的内容(FlateDecodeStream)(以及长度),并生成一个新的单页页面。
我可以使用PDF了;但是,不会显示小徽标,并且Adobe Reader表示正确显示PDF存在问题(谷歌浏览器chrome和edge只是不显示徽标,没有错误消息)。
我试图最后弄乱外部参照表(手动调整值),但是得到了相同的结果。
有没有对PDF有一定了解的人可以给我任何输入?
我正在上传template_pdf和其他我要提取数据并创建第三个pdf的文件(使用模板pdf,但包含另一个PDF的内容)。另外,我还将上传我手工制作的,显示错误的PDF(它显示数据但没有JPEG徽标)。
这里的所有内容:https://drive.google.com/drive/folders/1tsGIbtbfwuATPQ6a_VPjnxLT4ozzNt0s?usp=sharing
我一直在使用HxD进行所有操作(以查看十六进制内容并复制\粘贴数据)
预先感谢
编辑:我正在添加当前用于生成PDF的代码。即使外部参照表正常(具有正确的位置),其也是无效的PDF。该代码非常丑陋,但是现在我正在寻找使它起作用的方法(而不是编写一个不错的代码)
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var jpegLogo = File.ReadAllBytes(@"C:\test\Ginfes-Reboot\jpegLogo.raw");
var pdfStream = File.ReadAllBytes(@"C:\test\Ginfes-Reboot\pdfStream.raw");
using (BinaryWriter b = new BinaryWriter(
File.Open(@"C:\test\Ginfes-Reboot\newPdf_newmethod.pdf", FileMode.Create)))
{
WritePDFAgain(b,jpegLogo,pdfStream);
}
}
private static void WritePDFAgain(BinaryWriter b, byte[] jpegLogo,byte[] pdfStream)
{
List<long> offSets = new List<long>();
string str = "%PDF-1.4" + "\n";
var byteArr = Encoding.ASCII.GetBytes(str);
b.Write(byteArr);
byteArr = StringToByteArray("25E2E3CFD30A");
b.Write(byteArr);
offSets.Add(b.BaseStream.Position);//0
str = "3 0 obj" + "\n" + "<</Type/XObject/ColorSpace/DeviceRGB/Subtype/Image/BitsPerComponent 8/Width 60/Length 3857/Height 60/Filter/DCTDecode>>stream" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(jpegLogo);
b.Write(Encoding.ASCII.GetBytes("\n"));
b.Write(Encoding.ASCII.GetBytes("endstream" +"\n" + "endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//1
str = "4 0 obj" + "\n" + "<</Length " + pdfStream.Length + "/Filter/FlateDecode>>stream" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(pdfStream);
b.Write(Encoding.ASCII.GetBytes("\n"));
b.Write(Encoding.ASCII.GetBytes("endstream" + "\n" + "endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//2
str = "1 0 obj" + "\n" + "<</Group<</Type/Group/CS/DeviceRGB/S/Transparency>>/Parent 5 0 R/Contents 4 0 R/Type/Page/Resources<</XObject<</img0 3 0 R>>/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]/ColorSpace<</CS/DeviceRGB>>/Font<</F1 2 0 R>>>>/MediaBox[0 0 595 936]>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//3
str = "6 0 obj" + "\n" + "[1 0 R/XYZ 0 814 0]" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//4
str = "2 0 obj" + "\n" + "<</BaseFont/Helvetica/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//5
str = "5 0 obj" + "\n" + "<</ITXT(2.1.7)/Type/Pages/Count 1/Kids[1 0 R]>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//6
str = "7 0 obj" + "\n" + "<</Names[(JR_PAGE_ANCHOR_0_1) 6 0 R]>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//7
str = "8 0 obj" + "\n" + "<</Dests 7 0 R>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//8
str = "9 0 obj" + "\n" + "<</Names 8 0 R/Type/Catalog/ViewerPreferences<</PrintScaling/AppDefault>>/Pages 5 0 R>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
offSets.Add(b.BaseStream.Position);//9
str = "10 0 obj" + "\n" + @"<</Creator(JasperReports \(nfs_novo\))/Producer(iText 2.1.7 by 1T3XT)/ModDate(D:20191211152903-03'00')/CreationDate(D:20191211152903-03'00')>>" + "\n";
b.Write(Encoding.ASCII.GetBytes(str));
b.Write(Encoding.ASCII.GetBytes("endobj" + "\n"));
b.Write(Encoding.ASCII.GetBytes("xref" + "\n" + "0 11" + "\n"));
b.Write(Encoding.ASCII.GetBytes("0000000000 65535 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("000000" + offSets.ElementAt(2) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("000000" + offSets.ElementAt(4) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("00000000"+ offSets.ElementAt(0) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("000000" + offSets.ElementAt(1) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("000000" + offSets.ElementAt(5) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("000000" + offSets.ElementAt(3) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("00000" + offSets.ElementAt(6) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("00000" + offSets.ElementAt(7) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("00000" + offSets.ElementAt(8) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("00000" + offSets.ElementAt(9) + " 00000 f " + "\n"));
b.Write(Encoding.ASCII.GetBytes("trailer" + "\n" + "<</Root 9 0 R/ID [<10a2f7fd162aa44a268ebb6f31cc98c4><c36ebb9dc93cd9a72f229f618092eeb0>]/Info 10 0 R/Size 11>>" + "\n"));
b.Write(Encoding.ASCII.GetBytes("startxref" + "\n" + (b.BaseStream.Position + 6) + "%%EOF" + "\n"));
}
使用的文件: https://drive.google.com/drive/folders/1i3J-yioFvcoiakyc_Wi8ddn9g6Pxy7zd?usp=sharing
答案 0 :(得分:1)
大部分时间都在那儿;从示例中生成的PDF的唯一问题是pdfStream
中引用的图像资源被命名为img10
,而在创建资源字典时分配的名称是img0
。 / p>
下面是一些代码,这些代码将标识正确的引用资源(在页面内容上使用正则表达式),然后您可以在构建字典时使用它。
您需要以下其他using
指令:
using System.IO.Compression;
using System.Text.RegularExpressions;
此方法解压缩页面内容流并匹配图像资源名称:
private static string GetImageResourceName(byte[] pdfStream) {
using (MemoryStream ms = new MemoryStream(pdfStream)) {
ms.Seek(2, SeekOrigin.Begin); // skip first 2 bytes (zlib header)
using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress)) {
using (StreamReader sr = new StreamReader(ds)) {
string contents = sr.ReadToEnd();
// PostScript command referencing the image resource looks like: /img123 Do
return Regex.Match(contents, @"\b(img\d+)\s+Do\b").Groups[1].Value;
}
}
}
}
最后,您只需要在WritePDFAgain
方法中更改此行:
str = String.Format(
"1 0 obj\n<</Group<</Type/Group/CS/DeviceRGB/S/Transparency>>"
+ "/Parent 5 0 R/Contents 4 0 R/Type/Page/Resources<</XObject"
+ "<</{0} 3 0 R>>/ProcSet [/PDF /Text /ImageB /ImageC "
+ "/ImageI]/ColorSpace<</CS/DeviceRGB>>/Font<</F1 2 0 R>>>>"
+ "/MediaBox[0 0 595 936]>>\n",
GetImageResourceName(pdfStream)
);
根据我在评论中的免责声明,此代码仅适用于这种非常特殊的情况和输入数据。这绝不是通用解决方案,但我认为您会接受。
我要重申一点,如果您打算不为此使用任何外部库,那么您很可能最终会编写自己的库(尽管这是一个非常基本的库)。