C# 无法使用MemoryStream合并2个PDF
我有一个c#类,它接受HTML并使用wkhtmltopdf将其转换为PDF。C# 无法使用MemoryStream合并2个PDF,c#,wkhtmltopdf,C#,Wkhtmltopdf,我有一个c#类,它接受HTML并使用wkhtmltopdf将其转换为PDF。 正如您将在下面看到的,我正在生成3个PDF—横向、纵向和两者的组合。 properties对象包含作为字符串的html以及横向/纵向的参数 System.IO.MemoryStream PDF = new WkHtmlToPdfConverter().GetPdfStream(properties); System.IO.FileStream file = new System.IO.FileStream("abc_l
正如您将在下面看到的,我正在生成3个PDF—横向、纵向和两者的组合。
properties
对象包含作为字符串的html以及横向/纵向的参数
System.IO.MemoryStream PDF = new WkHtmlToPdfConverter().GetPdfStream(properties);
System.IO.FileStream file = new System.IO.FileStream("abc_landscape.pdf", System.IO.FileMode.Create);
PDF.Position = 0;
properties.IsHorizontalOrientation = false;
System.IO.MemoryStream PDF_portrait = new WkHtmlToPdfConverter().GetPdfStream(properties);
System.IO.FileStream file_portrait = new System.IO.FileStream("abc_portrait.pdf", System.IO.FileMode.Create);
PDF_portrait.Position = 0;
System.IO.MemoryStream finalStream = new System.IO.MemoryStream();
PDF.CopyTo(finalStream);
PDF_portrait.CopyTo(finalStream);
System.IO.FileStream file_combined = new System.IO.FileStream("abc_combined.pdf", System.IO.FileMode.Create);
try
{
PDF.WriteTo(file);
PDF.Flush();
PDF_portrait.WriteTo(file_portrait);
PDF_portrait.Flush();
finalStream.WriteTo(file_combined);
finalStream.Flush();
}
catch (Exception)
{
throw;
}
finally
{
PDF.Close();
file.Close();
PDF_portrait.Close();
file_portrait.Close();
finalStream.Close();
file_combined.Close();
}
pdf“abc_landscape.pdf”和“abc_ratio.pdf”按预期正确生成,但当我尝试将两者合并到第三个pdf(abc_combined.pdf)中时,操作失败。
我正在使用
MemoryStream
执行合并,在调试时,我可以看到finalStream.length
等于前两个PDF的总和。但是当我试图打开PDF时,我只看到两个PDF中的一个的内容。如下所示: 此外,当我试图关闭“abc_combined.pdf”时,系统会提示我保存它,这在其他两个pdf中不会发生。 下面是一些我已经尝试过但没有效果的东西:
如果需要,下面是
GetPdfStream()
方法的详细说明var htmlStream=newmemoryStream();
var writer=新的StreamWriter(htmlStream);
writer.Write(htmlString);
writer.Flush();
htmlStream.Position=0;
返回htmlStream;
过程=过程启动(psi);
process.EnableRaisingEvents=true;
尝试
{
process.Start();
process.BeginErrorReadLine();
var inputTask=Task.Run(()=>
{
htmlStream.CopyTo(process.StandardInput.BaseStream);
process.StandardInput.Close();
});
//将输出复制到memorystream
MemoryStream pdf=新的MemoryStream();
var outputTask=Task.Run(()=>
{
process.StandardOutput.BaseStream.CopyTo(pdf);
});
Task.WaitAll(输入任务、输出任务);
process.WaitForExit();
//重置存储器流读取位置
pdf.Position=0;
返回pdf;
}
捕获(例外情况除外)
{
掷骰子;
}
最后
{
process.Dispose();
}
这个来自Stack Overflow()的答案对我有用:
using (PdfDocument one = PdfReader.Open("pdf 1.pdf", PdfDocumentOpenMode.Import))
using (PdfDocument two = PdfReader.Open("pdf 2.pdf", PdfDocumentOpenMode.Import))
using (PdfDocument outPdf = new PdfDocument())
{
CopyPages(one, outPdf);
CopyPages(two, outPdf);
outPdf.Save("file1and2.pdf");
}
void CopyPages(PdfDocument from, PdfDocument to)
{
for (int i = 0; i < from.PageCount; i++)
{
to.AddPage(from.Pages[i]);
}
}
使用(pdfdocumentone=PdfReader.Open(“pdf 1.pdf”,PdfDocumentOpenMode.Import))
使用(PdfDocument two=PdfReader.Open(“pdf 2.pdf”,PdfDocumentOpenMode.Import))
使用(PdfDocument outPdf=new PdfDocument())
{
复印页(一页,输出页);
复印页(两页,输出DF);
outPdf.Save(“file1和file2.pdf”);
}
作废副本页(PDF文档发件人、PDF文档收件人)
{
for(int i=0;i
PDF的工作原理并非如此。PDF是特定格式的结构化文件。
您不能只将一个字节附加到另一个字节,然后期望结果是有效的文档
您将拥有一个能够理解格式并能为您执行操作的用户,或者开发您自己的解决方案。在不使用第三方库的情况下,将pdf合并到C#或任何其他语言中是不直接的
我假设您不使用库的要求是,大多数免费库、nuget包都有商业使用的限制或/和成本
我做了研究,发现了一个名为with package的开源库,它也可用于Java。它是免费的,不受限制(如果你愿意捐赠)。这个图书馆有很多书。一个这样的文档可以将2个或多个文档合并到一个文档中
我举了一个例子,将一个包含多个pdf文件的文件夹合并并保存到同一个或另一个文件夹中。也可以使用MemoryStream,但我觉得在这种情况下没有必要
代码是自我解释的,这里的关键点是使用序列化模式enum.Incremental
:
public static void MergePdf(string srcPath, string destFile)
{
var list = Directory.GetFiles(Path.GetFullPath(srcPath));
if (string.IsNullOrWhiteSpace(srcPath) || string.IsNullOrWhiteSpace(destFile) || list.Length <= 1)
return;
var files = list.Select(File.ReadAllBytes).ToList();
using (var dest = new org.pdfclown.files.File(new org.pdfclown.bytes.Buffer(files[0])))
{
var document = dest.Document;
var builder = new org.pdfclown.tools.PageManager(document);
foreach (var file in files.Skip(1))
{
using (var src = new org.pdfclown.files.File(new org.pdfclown.bytes.Buffer(file)))
{ builder.Add(src.Document); }
}
dest.Save(destFile, SerializationModeEnum.Incremental);
}
}
输入示例PDF文档A和PDF文档B 输出示例 我的研究链接:
PDF文件不仅仅是文本和图像。在幕后有一个严格的文件格式,它描述了PDF版本、文件中包含的对象以及在哪里可以找到它们 为了合并2个PDF,您需要操纵流 首先,您只需要保存其中一个文件的头。这很简单,因为这只是第一行 然后你可以写第一页的正文,然后写第二页 现在最困难的部分,也可能是说服您使用库的部分,是您必须重新构建外部参照表。外部参照表是一个交叉引用表,它描述文档的内容,更重要的是描述在何处查找每个元素。您必须计算第二页的字节偏移量,将其外部参照表中的所有元素移动那么多,然后将其外部参照表添加到第一页。您还需要确保在外部参照表中为分页符创建对象 完成后,您需要重新构建文档拖车,它告诉应用程序文档的各个部分在哪里 看
这不是一件小事,您最终将重新编写大量已经存在的代码。我正在寻找一些没有PdfSharp@Sanketh.K.JainMemoryStream独占还是允许使用其他技术?()只需C#。没有其他技术。到目前为止,我在一个流中有我的PDF,它是作为wkhtmltopdf的输出生成的。我不明白你为什么不能在已经使用wkhtmltopdf的情况下使用另一个nuget包,但这只是我的意见。我理解。但这就是我得到的要求:PPdf是一种结构化文件格式,这意味着它由许多小部分组成,可以构建一个完整的文档。格式见本文件第7.5节
var srcPath = @"C:\temp\pdf\input";
var destFile = @"c:\temp\pdf\output\merged.pdf";
MergePdf(srcPath, destFile);