我错过了什么步骤或顺序错误导致此 PDF 写入失败?

What step am I missing or do I have in the wrong order that is causing this PDF writing to fail?

我有这段代码可以生成 PDF 文件,但它打不开,当我尝试时 Edge 告诉我,“无法打开 PDF。有什么东西阻止了这个 PDF 打开。 "

这是不知何故搞砸了的代码 up/haywire(删除了不相关和冗余的代码):

public static void GenerateAndEmailScheduleToChairmen(int year, int month)
{
    . . .
    try
    {
        using (var ms = new MemoryStream())
        {
            using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 
25))
            {
                using (var writer = PdfWriter.GetInstance(doc, ms))
                {
                    doc.Open();

                    // Title
                    PdfPTable titleTable = new PdfPTable(1);
                    Paragraph title = new Paragraph(
                        $"CHAIRMEN'S SCHEDULE FOR 
{AYttFMConstsAndUtils.GetMonthForInt(month)}, {year}");
                    title.Font.SetFamily("Verdana");
                    title.Font.Size = 16;

                    var titleCell = new PdfPCell();
                    titleCell.AddElement(title);
                    titleTable.AddCell(titleCell);
                    doc.Add(titleTable);

                    // Column Headings
                    PdfPTable tblHeadings = new PdfPTable(6)
                    {
                        WidthPercentage = 80,
                        SpacingBefore = 10f
                    };
                    float[] headingRowWidths = new float[] {180f, 180f, 
180f, 180f, 100f, 180f};
                    tblHeadings.SetWidths(headingRowWidths);
                    tblHeadings.HorizontalAlignment = Element.ALIGN_LEFT;

                    Phrase phraseWeekBeginningHeading = new Phrase("Week 
Beginning", courier11BoldYellow);
                    PdfPCell cellWeekBeginningHeading = 
GetCellForBorderedTable(phraseWeekBeginningHeading,
                        Element.ALIGN_CENTER, BaseColor.BLUE);
                    tblHeadings.AddCell(cellWeekBeginningHeading);

                    . . .

                    // Main Contents

                    DateTime prevD8 = 
humanFriendlyAssignmentVals[0].WeekOfAssignment.Date;
                    foreach (AssignmentStudentMashup asmRec in 
humanFriendlyAssignmentVals)
                    {
                        // add a paragraph break when the week changes
                        PdfPTable tblRow;
                        if (asmRec.WeekOfAssignment.Date != prevD8)
                        {
                            tblRow = new PdfPTable(6)
                            {
                                WidthPercentage = 80,
                                SpacingBefore = 10f
                            };
                            headingRowWidths = new[] {180f, 180f, 180f, 
180f, 100f, 180f};
                            tblRow.SetWidths(headingRowWidths);
                            tblRow.HorizontalAlignment = Element.ALIGN_LEFT;

                            // Add blank row
                            var phraseblankRow = new Phrase();
                            var cellBlankRow = new PdfPCell(phraseblankRow) 
{BorderWidth = 0};
                            tblRow.AddCell(cellBlankRow);
                        }
                        prevD8 = asmRec.WeekOfAssignment;
                        tblRow = new PdfPTable(6)
                        {
                            WidthPercentage = 80,
                            SpacingBefore = 10f
                        };
                        headingRowWidths = new[] {180f, 180f, 180f, 180f, 
100f, 180f};
                        tblRow.SetWidths(headingRowWidths);
                        tblRow.HorizontalAlignment = Element.ALIGN_LEFT;

                        var phraseWeekBeginning = new 
Phrase(asmRec.WeekOfAssignment.ToLongDateString(),
                            courier11BoldYellow);
                        var cellWeekBeginning = 
GetCellForBorderedTable(phraseWeekBeginning,
                            Element.ALIGN_CENTER, BaseColor.BLUE);
                        tblRow.AddCell(cellWeekBeginning);

                        . . .
                        doc.Add(tblHeadings);
                    } // writer
                    var bytes = ms.ToArray();
                    String PDFFileName = 
$"ChairmensCounselInfo_{DateTime.Now.ToShortTimeString()}.pdf";
                    PDFFileName = PDFFileName.Replace(":", "_");
                    var chairmansPDFFile = $"C:\AYttFMApp\{PDFFileName}";
                    File.WriteAllBytes(chairmansPDFFile, bytes);
                    MessageBox.Show($"{PDFFileName} written");
                }
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(${ex.Message});
    }
}

我看到 "file written" messagebox.show,但随后出现“无法访问已关闭的流

更新

我现在正在创建 MemoryStream,但没有使用关闭,并在编写之前关闭了文档,但我仍然收到一条消息,指出无法打开 PDF 文件(尽管它确实有一些内容 (2KB))。

我认为 "writer" 至少是部分问题,因为没有它,PDF 是 0KB,但是有了它,"writer" 是灰色的,好像它没有被使用.现在这是我的代码(只有上面提到的那些差异):

    try
    {
        var ms = new MemoryStream();
        using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
        {
            using (var writer = PdfWriter.GetInstance(doc, ms))
            {
                doc.Open();

                // Title
                PdfPTable titleTable = new PdfPTable(1);
                Paragraph title = new Paragraph(
                    $"CHAIRMEN'S SCHEDULE FOR 
{AYttFMConstsAndUtils.GetMonthForInt(month)}, {year}");
                title.Font.SetFamily("Verdana");
                title.Font.Size = 16;

                var titleCell = new PdfPCell();
                titleCell.AddElement(title);
                titleTable.AddCell(titleCell);
                doc.Add(titleTable);

                // Column Headings
                PdfPTable tblHeadings = new PdfPTable(6)
                {
                    WidthPercentage = 80,
                    SpacingBefore = 10f
                };
                float[] headingRowWidths = new float[] { 180f, 180f, 180f, 
180f, 100f, 180f };
                tblHeadings.SetWidths(headingRowWidths);
                tblHeadings.HorizontalAlignment = Element.ALIGN_LEFT;

                Phrase phraseWeekBeginningHeading = new Phrase("Week 
Beginning", courier11BoldYellow);
                PdfPCell cellWeekBeginningHeading = 
GetCellForBorderedTable(phraseWeekBeginningHeading,
                    Element.ALIGN_CENTER, BaseColor.BLUE);
                tblHeadings.AddCell(cellWeekBeginningHeading);

                . . .

                // Main Contents

                DateTime prevD8 = 
humanFriendlyAssignmentVals[0].WeekOfAssignment.Date;
                foreach (AssignmentStudentMashup asmRec in 
humanFriendlyAssignmentVals)
                {
                    // add a paragraph break when the week changes
                    PdfPTable tblRow;
                    if (asmRec.WeekOfAssignment.Date != prevD8)
                    {
                        tblRow = new PdfPTable(6)
                        {
                            WidthPercentage = 80,
                            SpacingBefore = 10f
                        };
                        headingRowWidths = new[] { 180f, 180f, 180f, 180f, 
100f, 180f };
                        tblRow.SetWidths(headingRowWidths);
                        tblRow.HorizontalAlignment = Element.ALIGN_LEFT;

                        // Add blank row
                        var phraseblankRow = new Phrase();
                        var cellBlankRow = new PdfPCell(phraseblankRow) 
{ BorderWidth = 0 };
                        tblRow.AddCell(cellBlankRow);
                    }
                    prevD8 = asmRec.WeekOfAssignment;
                    tblRow = new PdfPTable(6)
                    {
                        WidthPercentage = 80,
                        SpacingBefore = 10f
                    };
                    headingRowWidths = new[] { 180f, 180f, 180f, 180f, 100f, 
180f };
                    tblRow.SetWidths(headingRowWidths);
                    tblRow.HorizontalAlignment = Element.ALIGN_LEFT;

                    var phraseWeekBeginning = new 
Phrase(asmRec.WeekOfAssignment.ToLongDateString(),
                        courier11BoldYellow);
                    var cellWeekBeginning = 
GetCellForBorderedTable(phraseWeekBeginning,
                        Element.ALIGN_CENTER, BaseColor.BLUE);
                    tblRow.AddCell(cellWeekBeginning);

                    . . .
                    var phraseCounselPoint = new 
Phrase(asmRec.CounselPointStr, courier11BoldYellow);
                    var cellCounselPoint 
GetCellForBorderedTable(phraseCounselPoint, Element.ALIGN_CENTER,
                        BaseColor.BLUE);
                    tblRow.AddCell(cellCounselPoint);
                    doc.Add(tblHeadings);
                } // writer
                var bytes = ms.ToArray();
                String PDFFileName = 
$"ChairmensInfo_{DateTime.Now.ToShortTimeString()}.pdf";
                PDFFileName = PDFFileName.Replace(":", "_");
                var chairmansPDFFile = $"C:\AYttFMApp\{PDFFileName}";
                doc.Close();
                File.WriteAllBytes(chairmansPDFFile, bytes);
                MessageBox.Show($"{PDFFileName} written");
            }
        }
    }
    catch (DocumentException dex)
    {
        MessageBox.Show($"DocumentException: {dex.Message}");
        throw;
    }
    catch (IOException ioex)
    {
        MessageBox.Show($"IOException: {ioex.Message}");
        throw;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"General Exception: {ex.Message}");
    }

我没有看到任何异常消息。

更新 2

好的,这就是工作所需:

var ms = new MemoryStream();
using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
{
    PdfWriter.GetInstance(doc, ms);
    doc.Open();
    . . . // contents added to the file, same as before
    doc.Add(tblHeadings);
} // using doc
var bytes = ms.ToArray();
String PDFFileName = $"ChairmensCounselInfo_{DateTime.Now.ToShortTimeString()}.pdf";
PDFFileName = PDFFileName.Replace(":", "_");
var chairmansPDFFile = $"C:\AYttFMApp\{PDFFileName}";
File.WriteAllBytes(chairmansPDFFile, bytes);
MessageBox.Show($"{PDFFileName} written");

您正在使用 MemoryStream 创建一个 byte 数组 ,然后 Document 关闭。这会导致 PDF 不完整。

在创建 Documentusing 的末尾,PDF 已完成(例如,编写了基本的交叉引用 table),但到那时,您已经使用不完整的流写入了PDF文件。

如何解决这个问题?

不要使用 using 创建 MemoryStream。等到 Document 关闭,然后再将 MemoryStream 的字节写入 PDF 文件。

更新:

您在更新中没有正确遵循我的建议。你有这样的东西:

var ms = new MemoryStream();
using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
{
    using (var writer = PdfWriter.GetInstance(doc, ms))
    {
        doc.Open();
        // adding content
        var bytes = ms.ToArray();
        doc.Close();
        // write bytes to a file.
    }
}

正如我之前解释的,这是错误的。您正在将不完整的 PDF 的内容写入名为 bytes 的字节数组。该 PDF 已损坏,因为它没有交叉引用 table。交叉引用 table 仅在您 Close() 文档时创建,无论是显式还是隐式。您现在 Close() 在创建 bytes 数组后显式地创建文档。太晚了。

你需要这样的东西:

var ms = new MemoryStream();
using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
{
    var writer = PdfWriter.GetInstance(doc, ms));
    doc.Open();
    // adding content
}
var bytes = ms.ToArray();
// write bytes to a file

如果你不需要writer,你甚至可以这样做:

var ms = new MemoryStream();
using (var doc = new Document(PageSize.A4.Rotate(), 25, 25, 25, 25))
{
    PdfWriter.GetInstance(doc, ms));
    doc.Open();
    // adding content
}
var bytes = ms.ToArray();
// write bytes to a file

只需确保创建完整的 PDF:

  1. 不要在 writer Document 有机会关闭之前关闭。
  2. 不要使用 ms Document 有机会关闭之前。