将 iTextSharp PDF 作为内存流返回导致 StreamNotSupported

问题描述:

我正在 iTextSharp 中使用 PdfStamper 创建一个 PDF 文件,并将 PDF 作为内存流返回调用函数的对象,然后用于在 WinForms 的 Teleriks PDF 查看器组件中显示 PDF.

I'm creating a PDF file using the PdfStamper in iTextSharp and return the PDF as a memorystream object to the calling function, that is then used to display the PDF in Teleriks PDF Viewer Component for WinForms.

这就是目标.

现在,创建 PDF 正常工作,并将数据返回给 Calling 函数,在 Calling 函数中,我应该将内存流内容写入文件流,然后在 Adob​​e Reader 中打开它吗?很好.

Right now, creating the PDF works as it should, and it returns the data to the Calling function, and in the Calling function, should I write the memorystream contents to a file stream and then open it in Adobe Reader Everything looks just fine.

但是,如果我选择在 PDF 查看器控件中显示 PDF,我只会收到不支持的流类型"错误.

However, if I choose to display the PDF in the PDF Viewer Control I just get an "Unsupported Stream type" error.

现在,我发现 PDF 数据有问题,所以我决定创建 PDF 文件,将其保存到磁盘,然后在调用函数中将其读取到内存流并在 PDF 查看器中显示该内存流,对于一些对我来说未知的原因,有效......

Now, I figured something was wrong in the PDF data so I decided to create the PDF file, save it to disk, then read it to a memorystream in the Calling function and display that memorystream in the PDF Viewer and that, for some to me unknown reason, works....

我真的无法解决这个问题,需要一些帮助.

I really can't get my head around this and need some help.

所以,这行不通:

//The Calling function
private void dlgViewPDF_Load(object sender, EventArgs e)
{
    MemoryStream ms = PDFcreator.GeneratePDFdata(id);

   rPdfView.LoadDocument(ms);
}

//The PDF generator
public static MemoryStream GeneratePDFdata(string id)
{
    MemoryStream ms = new MemoryStream();

    string sTemplate = string.Concat(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "\template.pdf");

    PdfReader pdfReader = new PdfReader(sTemplate);
    PdfStamper pdfStamper = new PdfStamper(pdfReader, ms);

    PdfContentByte cb = pdfStamper.GetOverContent(1);

    BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, BaseFont.EMBEDDED);
    BaseFont baseFontBold = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1250, BaseFont.EMBEDDED);
    cb.SetColorFill(iTextSharp.text.Color.BLACK);
    cb.SetFontAndSize(baseFontBold, 14);

    cb.BeginText();
    cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "TEST!!", 385, 750, 0);
    cb.EndText();

    cb.SetColorStroke(new CMYKColor(0f, 0f, 0f, 1f));
    cb.SetColorFill(new CMYKColor(0f, 0f, 0f, 1f));

    cb.MoveTo(139, 398);
    cb.LineTo(146, 398);
    cb.LineTo(146, 391);
    cb.LineTo(139, 391);
    cb.ClosePathEoFillStroke();

    pdfStamper.Close();
    pdfReader.Close();

    return ms;
}

但是出于某种原因,这确实有效:

However THIS does work for some reason:

//The Calling function
private void dlgViewPDF_Load(object sender, EventArgs e)
{
    MemoryStream ms = new MemoryStream();

    FileStream file = new FileStream(@"c:	emp	estfile.pdf", FileMode.Open, FileAccess.Read);

    byte[] bytes = new byte[file.Length];
    file.Read(bytes, 0, (int)file.Length);
    ms.Write(bytes, 0, (int)file.Length);

    rPdfView.LoadDocument(ms);
}


//The PDF generator 
public static void GeneratePDFdata(string id)
{
    MemoryStream ms = new MemoryStream();

    string sTemplate = string.Concat(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "\template.pdf");

    PdfReader pdfReader = new PdfReader(sTemplate);

    FileStream fs = new FileStream(@"c:	emp	estfile.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
    PdfStamper pdfStamper = new PdfStamper(pdfReader, fs);

    PdfContentByte cb = pdfStamper.GetOverContent(1);

    BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, BaseFont.EMBEDDED);
    BaseFont baseFontBold = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1250, BaseFont.EMBEDDED);
    cb.SetColorFill(iTextSharp.text.Color.BLACK);
    cb.SetFontAndSize(baseFontBold, 14);

    cb.BeginText();
    cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "TEST!!", 385, 750, 0);
    cb.EndText();

    cb.SetColorStroke(new CMYKColor(0f, 0f, 0f, 1f));
    cb.SetColorFill(new CMYKColor(0f, 0f, 0f, 1f));

    cb.MoveTo(139, 398);
    cb.LineTo(146, 398);
    cb.LineTo(146, 391);
    cb.LineTo(139, 391);
    cb.ClosePathEoFillStroke();

    pdfStamper.Close();
    pdfReader.Close();
}

但是为什么呢?如果用户愿意,我宁愿将其全部保存在内存中,并让用户保存生成的 PDF,而不必将其写入磁盘然后显示.

But why? I'd rather keep it all in memory and let the user save the resulting PDF if he/she so wishes than having to write it to disk and then displaying it.

出现问题是因为在 PdfStamper 关闭时内存流被隐式关闭.为了防止这个添加

The problem arises because the memory stream gets implicitly closed when the PdfStamper is closed. To prevent this add

pdfStamper.Writer.CloseStream = false;

之前

pdfStamper.Close();

这会指示压模不要关闭流.

This instructs the stamper not to close the stream.