C# 将iTextSharp PDF作为memorystream返回会导致StreamNotSupported

C# 将iTextSharp PDF作为memorystream返回会导致StreamNotSupported,c#,winforms,pdf,telerik,itextsharp,C#,Winforms,Pdf,Telerik,Itextsharp,我正在使用iTextSharp中的PdfStamper创建一个PDF文件,并将PDF作为memorystream返回 对象调用函数,该函数随后用于在Teleriks PDF Viewer组件中显示用于WinForms的PDF 这就是目标 现在,创建PDF正常工作,它将数据返回给调用函数,在调用函数中,我是否应该将memorystream内容写入文件流,然后在Adobe Reader中打开它?一切看起来都很好 但是,如果我选择在PDF查看器控件中显示PDF,我只会得到一个“不支持的流类型”错误 现

我正在使用iTextSharp中的PdfStamper创建一个PDF文件,并将PDF作为memorystream返回 对象调用函数,该函数随后用于在Teleriks PDF Viewer组件中显示用于WinForms的PDF

这就是目标

现在,创建PDF正常工作,它将数据返回给调用函数,在调用函数中,我是否应该将memorystream内容写入文件流,然后在Adobe Reader中打开它?一切看起来都很好

但是,如果我选择在PDF查看器控件中显示PDF,我只会得到一个“不支持的流类型”错误

现在,我发现PDF数据中有问题,所以我决定创建PDF文件,将其保存到磁盘,然后在调用函数中将其读取到memorystream中,并在PDF查看器中显示该memorystream,并且由于某些未知的原因,它可以工作

我真的想不起来了,需要一些帮助

因此,这个不起作用:

//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;
}
但是,出于某些原因,这确实有效:

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

    FileStream file = new FileStream(@"c:\temp\testfile.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:\temp\testfile.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,而不必将其写入磁盘,然后显示出来。

问题出现了,因为当PdfStamper关闭时,内存流会隐式关闭。要防止这种情况,请添加

pdfStamper.Writer.CloseStream = false;
以前

pdfStamper.Close();

这将指示压模不关闭流。

对于iText 7,语法已从更改为

您可以使用
SetCloseStream()
方法阻止写入程序关闭流:

PdfWriter writer = new PdfWriter(stream);
writer.SetCloseStream(false);

pdfStamper.Close()
之前尝试
pdfStamper.Writer.CloseStream=false
。这就像一个符咒。添加它作为答复,我会将其标记为答复。谢谢你的帮助。:)如果您想让您的生活更轻松,请不要传递流,始终通过调用
MemoryStream
上的
ToArray()
来传递原始字节。如果您传递字节,您不必担心有人意外地将其关闭在您或流中的当前位置。