c# - 使用 PDFSharp 将多个 PDF 合并为一个非常大的 PDF 而不会耗尽内存
问题描述
我正在使用 PDFsharp 将大量文件(存储在磁盘上)合并为一个 PDF。有时 PDF 可以大到 700MB。我正在使用提供的示例代码,它基本上创建了一个输出PdfDocument
,向其中添加页面,然后调用 outputDocument.Save(destinationPath),因此使用的内存量与生成的文档的大小大致相同。
有没有办法将更改流式传输到文件以避免内存消耗?如果没有,是否有办法利用 MigraDoc 来做到这一点?
更新
根据评论中的建议,我整理了一些代码来关闭和重新打开文档,虽然内存使用受到控制并且文件确实增长了,但它似乎没有附加页面。如果我将“路径”设置为包含 3000 个单页文件的列表,我仍然会得到一个 500 页的文档。这是代码:
var destinationFile = "c:\\test.pdf";
var directory = Path.GetDirectoryName(destinationFile);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var fs = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var outputDocument = new PdfDocument(fs);
var count = 0;
// Iterate files (paths is a List<string> collection)
foreach (string path in paths)
{
var inputDocument = PdfReader.Open(path, PdfDocumentOpenMode.Import);
// Iterate pages
for (int idx = 0; idx < inputDocument.PageCount; idx++)
{
// Get the page from the external document...
PdfPage page = inputDocument.Pages[idx];
// ...and add it to the output document.
outputDocument.AddPage(page);
}
inputDocument.Dispose();
count++;
if (count % 500 == 0 || count == paths.Count)
{
outputDocument.Close();
fs.Close();
fs.Dispose();
if (count < paths.Count)
{
fs = new FileStream(destinationFile, FileMode.Append, FileAccess.Write);
outputDocument = new PdfDocument(fs);
}
}
}
更新 2
这是一些使用 PDFReader 关闭和重新打开文档的新代码。程序正在合并 2000 个 4 页 140KB PDF,输出文件为 273MB。我试过没有关闭和重新打开,关闭和重新打开每 1000、500、250 和 100 个文件。结果如下:
无间隔:21 秒,最大内存 330MB 1000 间隔:30 秒,最大内存 490MB 500 间隔:55 秒,最大内存 710MB 250 间隔:1 分 35 秒,最大内存 780MB 100 间隔:2 分 55 秒,最大内存 850mb
class Program
{
public static void Main(string[] args)
{
var files = new List<string>();
var basePath = AppDomain.CurrentDomain.BaseDirectory;
for (var i = 0; i < 2000; i++)
{
files.Add($"{basePath}\\sample.pdf");
}
DoMerge(files, $"{basePath}\\output.pdf");
}
private static void DoMerge(List<string> paths, string destinationFile)
{
var directory = Path.GetDirectoryName(destinationFile);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
var outputDocument = new PdfDocument();
var count = 0;
// Iterate files
foreach (string path in paths)
{
// Open the document to import pages from it.
try
{
var inputDocument = PdfReader.Open(path, PdfDocumentOpenMode.Import);
// Iterate pages
for (int idx = 0; idx < inputDocument.PageCount; idx++)
{
// Get the page from the external document...
PdfPage page = inputDocument.Pages[idx];
// ...and add it to the output document.
outputDocument.AddPage(page);
}
inputDocument.Dispose();
count++;
if (count % 500 == 0 || count == paths.Count)
{
outputDocument.Save(destinationFile);
outputDocument.Close();
outputDocument.Dispose();
if (count < paths.Count)
{
outputDocument = PdfReader.Open(destinationFile, PdfDocumentOpenMode.Import);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
}
解决方案
为了减少内存占用,您可以不时关闭目标文件,然后再次打开它,并在其中附加更多 PDF 文件。
PDFsharp 不支持将数据交换到文件。
确保您的应用程序在 64 位模式下运行,以允许其使用超过 2 GiB 的 RAM。
推荐阅读
- python - 静态变量可以在python中声明为私有吗?
- ios - 自定义单元格不出现在 tableView
- spotfire - 需要在 spotfire 中显示选定月份 3 年的趋势分析
- javascript - 像在 IDE 中一样在文本区域中反应自动完成(例如 VS Code、Atom)
- python - Django:选择对象包含所有关键字
- c# - c#:在大写和小写中搜索 DataGridView 列文本
- java - 将值添加到 Java ENUM 以进行测试
- linux - 一般的颜色列表
- c++ - 违反 noexcept 保证的编译器警告或静态分析?
- python - .where 在 PySpark 中使用 LIKE 运算符的奇怪结果