【问题标题】:iTextSharp Pdf pages import memory issueiTextSharp Pdf 页面导入内存问题
【发布时间】:2011-06-25 08:43:34
【问题描述】:

我正在使用此代码将不同的 pdf 文件页面导入到单个文档中。当我导入大文件(200 页或以上)时,出现OutOfMemory 异常。我在这里做错了吗?

    private bool SaveToFile(string fileName)
    {
        try
        {
            iTextSharp.text.Document doc;
            iTextSharp.text.pdf.PdfCopy pdfCpy;
            string output = fileName;

            doc = new iTextSharp.text.Document();
            pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(output, System.IO.FileMode.Create));
            doc.Open();

            foreach (DataGridViewRow item in dvSourcePreview.Rows)
            {
                string pdfFileName = item.Cells[COL_FILENAME].Value.ToString();
                int pdfPageIndex = int.Parse(item.Cells[COL_PAGE_NO].Value.ToString());
                pdfPageIndex += 1;

                iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
                int pageCount = reader.NumberOfPages;

                // set page size for the documents
                doc.SetPageSize(reader.GetPageSizeWithRotation(1));

                iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader, pdfPageIndex);
                pdfCpy.AddPage(page);

                reader.Close();
            }

            doc.Close();

            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

【问题讨论】:

    标签: c# pdf itext


    【解决方案1】:

    您正在为每次传递创建一个新的PdfReader。这是非常低效的。而且因为每个实例都有一个 PdfImportedPage,所以所有那些(可能是多余的)PdfReader 实例都不会被 GC 处理。

    建议:

    1. 两次传球。首先建立一个文件和页面列表。其次依次对每个文件进行操作,因此您一次只有一个PdfReader“打开”。完成给定阅读器后,请使用PdfCopy.freeReader()。这几乎肯定会改变您添加页面的顺序(可能是一件非常糟糕的事情)。
    2. 一次通过。根据文件名缓存 PdfReader 实例。完成后再次使用 FreeReader……但是在退出循环之前,您可能无法释放它们中的任何一个。仅缓存可能就足以防止内存不足。
    3. 保持代码不变,但在关闭给定的PdfReader 实例后调用freeReader()

    【讨论】:

      【解决方案2】:

      我没有遇到 iTextSharp 的 OOM 问题。是用 iTextSharp 还是其他东西创建的 PDF?您能否将问题隔离为单个 PDF 或一组可能损坏的 PDF?下面是创建 10 个 PDF 的示例代码,每个 PDF 有 1,000 页。然后它再创建一个 PDF 并从这些 PDF 中随机抽取 1 页 500 次。在我的机器上运行需要一点时间,但我没有看到任何内存问题或任何东西。 (iText 5.1.1.0)

      using System;
      using System.Windows.Forms;
      using System.IO;
      using iTextSharp.text;
      using iTextSharp.text.pdf;
      
      namespace WindowsFormsApplication1
      {
          public partial class Form1 : Form
          {
              public Form1()
              {
                  InitializeComponent();
              }
      
              private void Form1_Load(object sender, EventArgs e)
              {
                  //Folder that we will be working in
      
                  string WorkingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Big File PDF Test");
      
                  //Base name of PDFs that we will be creating
                  string BigFileBase = Path.Combine(WorkingFolder, "BigFile");
      
                  //Final combined PDF name
                  string CombinedFile = Path.Combine(WorkingFolder, "Combined.pdf");
      
                  //Number of "large" files to create
                  int NumberOfBigFilesToMakes = 10;
      
                  //Number of pages to put in the files
                  int NumberOfPagesInBigFile = 1000;
      
                  //Number of pages to insert into combined file
                  int NumberOfPagesToInsertIntoCombinedFile = 500;
      
                  //Create our test directory
                  if (!Directory.Exists(WorkingFolder)) Directory.CreateDirectory(WorkingFolder);
      
                  //First step, create a bunch of files with a bunch of pages, hopefully code is self-explanatory
                  for (int FileCount = 1; FileCount <= NumberOfBigFilesToMakes; FileCount++)
                  {
                      using (FileStream FS = new FileStream(BigFileBase + FileCount + ".pdf", FileMode.Create, FileAccess.Write, FileShare.Read))
                      {
                          using (iTextSharp.text.Document Doc = new iTextSharp.text.Document(PageSize.LETTER))
                          {
                              using (PdfWriter writer = PdfWriter.GetInstance(Doc, FS))
                              {
                                  Doc.Open();
                                  for (int I = 1; I <= NumberOfPagesInBigFile; I++)
                                  {
                                      Doc.NewPage();
                                      Doc.Add(new Paragraph("This is file " + FileCount));
                                      Doc.Add(new Paragraph("This is page " + I));
                                  }
                                  Doc.Close();
                              }
                          }
                      }
                  }
      
                  //Second step, loop around pulling random pages from random files
      
                  //Create our output file
                  using (FileStream FS = new FileStream(CombinedFile, FileMode.Create, FileAccess.Write, FileShare.Read))
                  {
                      using (Document Doc = new Document())
                      {
                          using (PdfCopy pdfCopy = new PdfCopy(Doc, FS))
                          {
                              Doc.Open();
      
                              //Setup some variables to use in the loop below
                              PdfReader reader = null;
                              PdfImportedPage page = null;
                              int RanFileNum = 0;
                              int RanPageNum = 0;
      
                              //Standard random number generator
                              Random R = new Random();
      
                              for (int I = 1; I <= NumberOfPagesToInsertIntoCombinedFile; I++)
                              {
                                  //Just to output our current progress
                                  Console.WriteLine(I);
      
                                  //Get a random page and file. Remember iText pages are 1-based.
                                  RanFileNum = R.Next(1, NumberOfBigFilesToMakes + 1);
                                  RanPageNum = R.Next(1, NumberOfPagesInBigFile + 1);
      
                                  //Open the random file
                                  reader = new PdfReader(BigFileBase + RanFileNum + ".pdf");
                                  //Set the current page
                                  Doc.SetPageSize(reader.GetPageSizeWithRotation(1));
      
                                  //Grab a random page
                                  page = pdfCopy.GetImportedPage(reader, RanPageNum);
                                  //Add it to the combined file
                                  pdfCopy.AddPage(page);
      
                                  //Clean up
                                  reader.Close();
                              }
      
                              //Clean up
                              Doc.Close();
                          }
                      }
                  }
      
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-30
        • 1970-01-01
        • 2015-01-29
        • 1970-01-01
        • 2017-04-15
        相关资源
        最近更新 更多