iTextSharp Efficient Batch Pdf Generation From a 1 Page Template

十年热恋 提交于 2019-12-05 01:03:06

问题


I am generating a multiple page PDF using ITextSharp, each page having the sames template.

The problem is that the PDF grows in Phisical Size by the size of the template.

I HAVE to use ACROFIELDS.

How can I reduce the final file size ?

Here is a code snippet of the pdf handler:

public void ProcessRequest(HttpContext context)
{
    Context = context;
    Response = context.Response;
    Request = context.Request;

    try
    {
        LoadDataInternal();
    }
    catch (System.Threading.ThreadAbortException)
    {
        // no-op
    }
    catch (Exception ex)
    {
        Logger.LogError(ex);
        Response.Write("Error");
        Response.End();
    }

    Response.BufferOutput = true;
    Response.ClearHeaders();
    Response.ContentType = "application/pdf";

    if (true)
    {
        Response.AddHeader("Content-Disposition", "attachment; filename=" +
            (string.IsNullOrEmpty(DownloadFileName) ? context.Session.SessionID + ".pdf" : DownloadFileName));
    }

    PdfCopyFields copy
        = new PdfCopyFields(Response.OutputStream);
    // add a document
    for (int i = 0; i < dataset.Tables["Model"].Rows.Count; i++)
    {
        copy.AddDocument(new PdfReader(renameFieldsIn(TemplatePath, i)));

        // add a document           
    }        
    copy.SetFullCompression();                   
    // Close the PdfCopyFields object        
    copy.Close();       
}

private byte[] renameFieldsIn(String datasheet, int i)

{
    MemoryStream baos = new MemoryStream();
    // Create the stamper
    PdfStamper stamper = new PdfStamper(new PdfReader(GetTemplateBytes()), baos);
    // Get the fields
    AcroFields form = stamper.AcroFields;
    // Loop over the fields
    List<String> keys = new List<String>(form.Fields.Keys);
    foreach (var key in keys) 
    {
        // rename the fields
        form.RenameField(key, String.Format("{0}_{1}", key, i));
    }
    stamper.FormFlattening = true;
    stamper.FreeTextFlattening = true;
    stamper.SetFullCompression();
    SetFieldsInternal(form, i);
    // close the stamper
    stamper.Close();
    return baos.ToArray();
}

protected byte[] GetTemplateBytes()
{
    var data = Context.Cache[PdfTemplateCacheKey] as byte[];
    if (data == null)
    {
        data = File.ReadAllBytes(Context.Server.MapPath(TemplatePath));
        Context.Cache.Insert(PdfTemplateCacheKey, data,
            null, DateTime.Now.Add(PdfTemplateCacheDuration), Cache.NoSlidingExpiration);
    }
    return data;
}

回答1:


I have done something a little similar before and found that after combining all the pages, running the entire generated document through the PDFStamper again resulted in a noticeable compression of the file size.




回答2:


Ok, so a friend of mine came up with a solution. The only problem remaining is the amount of memory it takes to create a new PdfStamper. So here's the rewritten procedure.

Anyway. Hope this hepls anyone else. And if you have a better solution please don't be shy.

public void ProcessRequest (HttpContext context) 
{
    var watch = System.Diagnostics.Stopwatch.StartNew();
    Context = context;
    Response = context.Response;
    Request = context.Request;

    Response.BufferOutput = true;
    Response.ClearHeaders();
    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Disposition", "attachment; filename=itextsharp_multiple.pdf");

    var pageBytes = (byte[])null;
    var pagesAll = new List<byte[]>();        

    try 
    {
        for (int i = 0; i < GlobalHttpApplication.Model.TestData.Rows.Count; i++) 
        {
            PdfStamper pst = null;
            MemoryStream mstr = null;
            using (mstr = new MemoryStream()) 
            {
                try 
                {
                    PdfReader reader = new PdfReader(GetTemplateBytes());
                    pst = new PdfStamper(reader, mstr);
                    var acroFields = pst.AcroFields;

                    SetFieldsInternal(acroFields, 0);

                    pst.FormFlattening = true;
                    pst.SetFullCompression();

                } finally 
                {
                    if (pst != null)
                        pst.Close();
                }                    
            }
            pageBytes = mstr.ToArray();
            pagesAll.Add(pageBytes);

        }
    } finally 
    {

    }   

    Document doc = new Document(PageSize.A4);        
    var writer = PdfWriter.GetInstance(doc, Response.OutputStream);
    var copy2 = new PdfSmartCopy(doc, Response.OutputStream);
    doc.Open();
    doc.OpenDocument();

    foreach (var b in pagesAll) 
    {
        doc.NewPage();
        copy2.AddPage(copy2.GetImportedPage(new PdfReader(b), 1));
    }
    copy2.Close();
    watch.Stop();
    File.AppendAllText(context.Server.MapPath("~/App_Data/log.txt"), watch.Elapsed + Environment.NewLine);

}


来源:https://stackoverflow.com/questions/4725198/itextsharp-efficient-batch-pdf-generation-from-a-1-page-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!