Generating blank pdf when downloaded -ItextSharp

2019-04-12 22:54发布

问题:

I am trying to generate a simple PDF document, which can be downloadable from an asp.net webpage. This pdf document has a paragraph with a heading text and the rest of the content is been populated through a pre-filled DataTable instance. All columns, which I am trying to print here are text with an exception of one column being an image (thumbnail).

I can execute the attached code with no exceptions, the pdf document will be generated and downloaded to client browser.

Issue: User can view this downloaded pdf in their browser ( tested only with IE and Chrome) and can view all the contents in the pdf including thumbnails. However, all of the pdf pages are blank when they save this generated pdf to their local drive and opens it.

Have been breaking my head for a while and any hint would be really helpful.

Code which generate PDF on server side event

private void Download()
    {

        var document = new Document();

        try
        {
            var dataTable = GetDataTable(parameters); //this line create and fill a DataTable with some values


            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition","attachment;filename=sample.pdf");

            Response.Cache.SetCacheability(HttpCacheability.NoCache);

            PdfWriter writer = PdfWriter.GetInstance(document, Response.OutputStream);//get a pdf writer instance

            document.Open();

            //Create table

            var pdfTable = DocumentManager.CreateTable(dataTable.Columns.Count, new[] { 30f, 130f, 130f, 80f, 60f, 80f, 60f, 80f, 60f, 60f, 80f, 80f, 60f });

  //Create a simple heading
                var heading = new StringBuilder();
                heading.AppendLine("Summary");


            var contentFont = DocumentManager.GetFont(5);
            var genHeadingFont = DocumentManager.GetFont(6, true);

            var image = iTextSharp.text.Image.GetInstance(HttpContext.Current.Server.MapPath("/images/some.png"));
            image.WidthPercentage = 25;
            image.Alignment = iTextSharp.text.Image.ALIGN_RIGHT;
            document.Add(image);
            document.Add(new Paragraph(heading.ToString(), contentFont));
            //Create column heading
            DocumentManager.CreateColums(pdfTable, dataTable, genHeadingFont);
            //Create cells and fill with values
            DocumentManager.CreateCellAndFillValue(pdfTable, dataTable.Select(), contentFont, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
            document.Add(pdfTable);
            Response.Write(document);
            document.Close();

        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {

        }
    }

Referenced Methods ( Part of DocumentManager Class)

public static PdfPTable CreateTable(int columnSpan, float[] columnWidths)
        {
            var table = new PdfPTable(columnSpan);
            table.SetWidths(columnWidths);
            table.TotalWidth = 1000f;
            table.WidthPercentage = 100;

            return table;
        }

public static Font GetFont(int size, bool isBold = false)
        {
            return FontFactory.GetFont("Calibri", size, isBold ? Font.BOLD : Font.NORMAL);
        }
public static void CreateColums(PdfPTable pdfTable, DataTable dataColumns, Font columnsFont,
                                        List<string> columnsToExclude = null, BaseColor backGround = null)
        {
            columnsToExclude = columnsToExclude ?? new List<string>();
            foreach (
                var c in
                    from DataColumn c in dataColumns.Columns where !columnsToExclude.Contains(c.ColumnName) select c)
            {
                var cell = new PdfPCell(new Phrase(c.ColumnName, columnsFont)) { BackgroundColor = backGround ?? new BaseColor(164, 183, 210), HorizontalAlignment = Element.ALIGN_MIDDLE };
                cell.PaddingBottom = 3f;
                cell.PaddingTop = 3f;
                cell.PaddingLeft = 3f;
                cell.PaddingRight = 3f;
                pdfTable.AddCell(cell);
            }
        }



        public static void CreateCellAndFillValue(PdfPTable table, DataRow[] dataRows, Font cellFont,
                                                int[] columnIndex = null, string[] columnNames = null)
        {
            if (columnIndex != null && columnIndex.Length != 0)
            {
                CreateCellValueUsingIndex(table, dataRows, cellFont, columnIndex);
                return;
            }
            if (columnNames != null && columnNames.Length != 0)
            {
                CreateCellValueUsingColumnName(table, dataRows, cellFont, columnNames);

            }
        }


        public static void CreateCellValueUsingIndex(PdfPTable table, IEnumerable<DataRow> dataRows, Font cellFont, int[] columnIndex)
        {
            foreach (var r in dataRows)
            {
                foreach (var index in columnIndex)
                {
                    if (index != 1) //value columns
                    {
                        var cell = new PdfPCell(new Phrase(r[index].ToString(), cellFont));
                        cell.PaddingBottom = 2f;
                        cell.PaddingTop = 2f;
                        cell.PaddingLeft = 2f;
                        cell.PaddingRight = 2f;
                        cell.HorizontalAlignment = Element.ALIGN_CENTER;
                        table.AddCell(cell);
                    }
                    else //image columns
                    {
                        iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(r[index].ToString());
                        image.Alignment = iTextSharp.text.Image.ALIGN_CENTER;
                        PdfPCell imgCell = new PdfPCell();
                        imgCell.AddElement(new Chunk(image, 0, 0));
                        table.AddCell(imgCell);

                    }
                }
            }
        }

        public static void CreateCellValueUsingColumnName(PdfPTable table, IEnumerable<DataRow> dataRows, Font cellFont,
                                                string[] columnNames)
        {

            foreach (var r in dataRows)
            {
                foreach (var name in columnNames)
                {

                    table.AddCell(new Phrase(r[name].ToString(), cellFont));
                }
            }
        }

回答1:

You are mixing everything up so it may get a little confusing. separate what you want to do into their own functions.

The single responsibility of this method is to Create the PDF

private void CreatePdf(Stream output) {
    var document = new Document();

    try {
        var dataTable = GetDataTable(parameters); //this line create and fill a DataTable with some values
        //get a pdf writer instance
        PdfWriter writer = PdfWriter.GetInstance(document, output);
        //open the document
        document.Open();
        //Create table
        var pdfTable = DocumentManager.CreateTable(dataTable.Columns.Count, new[] { 30f, 130f, 130f, 80f, 60f, 80f, 60f, 80f, 60f, 60f, 80f, 80f, 60f });
        //Create a simple heading
        var heading = new StringBuilder();
        heading.AppendLine("Summary");

        var contentFont = DocumentManager.GetFont(5);
        var genHeadingFont = DocumentManager.GetFont(6, true);

        var image = iTextSharp.text.Image.GetInstance(HttpContext.Current.Server.MapPath("/images/some.png"));
        image.WidthPercentage = 25;
        image.Alignment = iTextSharp.text.Image.ALIGN_RIGHT;
        document.Add(image);
        document.Add(new Paragraph(heading.ToString(), contentFont));
        //Create column heading
        DocumentManager.CreateColums(pdfTable, dataTable, genHeadingFont);
        //Create cells and fill with values
        DocumentManager.CreateCellAndFillValue(pdfTable, dataTable.Select(), contentFont, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 });
        document.Add(pdfTable);

        // make sure any data in the buffer is written to the output stream
        writer.Flush();
    } finally {
        document.Close();
    }
}

This will then allow your Download to be a little more lean

private void Download() {
    Response.ContentType = "application/pdf;";
    Response.AddHeader("content-disposition","attachment;filename=sample.pdf");
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    // stream to store generated document
    var output = new MemoryStream();
    // generate document
    CreatePdf(output);
    // pass the generated data to the response output stream
    Response.OutputStream.Write(output.GetBuffer(), 0, output.Length);
}

By separating the responsibilities out you will notice where your mistake was in your original post. The document was flushed and closed completely before being sent in the response. This should allow for when you try to save the document that it has all the data it needs to save the complete document.



标签: c# asp.net itext