【发布时间】:2019-12-28 16:37:21
【问题描述】:
我有一个 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_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_portrait.pdf”按预期正确生成,但是当我尝试将两者合并为第三个 pdf (abc_combined.pdf) 时操作失败。
我正在使用MemoryStream 进行合并,在调试时,我可以看到finalStream.length 等于前两个PDF 的总和。但是当我尝试打开 PDF 时,我只看到两个 PDF 中的一个的内容。
同样可以在下面看到:
此外,当我尝试关闭“abc_combined.pdf”时,系统会提示我保存它,而其他 2 个 PDF 不会发生这种情况。
以下是我已经尝试过的一些事情,但无济于事:
- 将 CopyTo() 更改为 WriteTo()
- 将同一 PDF(横向或纵向)与其自身合并
如果需要,下面是GetPdfStream()方法的详细说明。
var htmlStream = new MemoryStream();
var writer = new StreamWriter(htmlStream);
writer.Write(htmlString);
writer.Flush();
htmlStream.Position = 0;
return htmlStream;
Process process = Process.Start(psi);
process.EnableRaisingEvents = true;
try
{
process.Start();
process.BeginErrorReadLine();
var inputTask = Task.Run(() =>
{
htmlStream.CopyTo(process.StandardInput.BaseStream);
process.StandardInput.Close();
});
// Copy the output to a memorystream
MemoryStream pdf = new MemoryStream();
var outputTask = Task.Run(() =>
{
process.StandardOutput.BaseStream.CopyTo(pdf);
});
Task.WaitAll(inputTask, outputTask);
process.WaitForExit();
// Reset memorystream read position
pdf.Position = 0;
return pdf;
}
catch (Exception ex)
{
throw ex;
}
finally
{
process.Dispose();
}
【问题讨论】:
-
Pdf 是一种结构化文件格式,这意味着它由许多微小的部分组成以构建完整的文档。请参阅adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/… 的第 7.5 节,这也是 pdf 阅读器阅读的格式。他们希望在一个文件中找到“标题、正文、交叉引用表、预告片”,但他们却找到了“标题、正文、交叉引用表、预告片、标题、正文、交叉引用表、预告片”。您需要一个理解这种格式的库(最简单),或者自己编写一个(规范在我之前提到的文档中)。
-
@Caramiriel 这很有意义。能否请您将此作为答案。我想将此标记为已解决
-
重复:stackoverflow.com/q/808670/2441442(赏金时不能关闭)
-
@ChristianGollhardt 虽然上述问题已经通过问题的实现得到了回答,但它并没有告诉我为什么我应该使用库。我正在寻找的答案要么是 Matthew 和 Caramiriel 提供的解释,要么是没有库的代码解决方案(我现在意识到这是一个不合理的期望)。请您重新考虑。谢谢。
标签: c# wkhtmltopdf