【问题标题】:Stream is not filled when using a MemoryStream for PdfWriter output from iTextSharp将 MemoryStream 用于 iTextSharp 的 PdfWriter 输出时未填充流
【发布时间】:2019-04-30 06:59:04
【问题描述】:

我有以下问题。

这段代码运行良好

private void ModifyAndSavePDF(Stream sourceFile, string text)
{
    using (var pdfWriterStream = new FileStream(@"d:/temp/test.pdf", FileMode.Create))
    {
        var reader = new PdfReader(sourceFile);
        var document = new Document(reader.GetPageSizeWithRotation(1));
        var writer = PdfWriter.GetInstance(document, pdfWriterStream);
        document.Open();
        for (var i = 1; i <= reader.NumberOfPages; i++)
        {
            document.NewPage();
            var importedPage = writer.GetImportedPage(reader, i);
            var contentByte = writer.DirectContent;
            //some more PDF editing stuff here. Not relevant.
        }
        document.Close();
        writer.Close();
        reader.Close();
    }
}

这很好用。 sourceFile 流包含大约 200Kb,保存的 pdf 看起来完全符合我的预期。我注意到的一件事是,在document.Close() 之前,pdfWriterStream 流的长度只有 800 字节左右。

我的问题是我不想将其保存到磁盘上的文件中,我希望将输出作为 MemoryStream 代替。但是,我无法按预期工作。我的第一次尝试是这样的:

private Stream ModifyAndSavePDF(Stream sourceFile, string text)
{
    using (var pdfWriterStream = new MemoryStream())
    {
        var reader = new PdfReader(sourceFile);
        var document = new Document(reader.GetPageSizeWithRotation(1));
        var writer = PdfWriter.GetInstance(document, pdfWriterStream);
        document.Open();
        for (var i = 1; i <= reader.NumberOfPages; i++)
        {
            document.NewPage();
            var importedPage = writer.GetImportedPage(reader, i);
            var contentByte = writer.DirectContent;
            //some more PDF editing stuff here. Not relevant.
        }
        document.Close();
        writer.Close();
        reader.Close();
    }
    return pdfWriterStream;
}

这当然行不通,因为当我调用document.Close() 时,pdfWriterStream 也被释放了,我无法读取流的内容。

第二次尝试:

private Stream ModifyAndSavePDF(Stream sourceFile, string text)
{
    var result = new MemoryStream();
    using (var pdfWriterStream = new MemoryStream())
    {
        var reader = new PdfReader(sourceFile);
        var document = new Document(reader.GetPageSizeWithRotation(1));
        var writer = PdfWriter.GetInstance(document, pdfWriterStream);
        document.Open();
        for (var i = 1; i <= reader.NumberOfPages; i++)
        {
            document.NewPage();
            var importedPage = writer.GetImportedPage(reader, i);
            var contentByte = writer.DirectContent;
            //some more PDF editing stuff here. Not relevant.
        }
        pdfWriterStream.Position = 0;
        pdfWriterStream.CopyTo(result);
        document.Close();
        writer.Close();
        reader.Close();
    }
    return result;
}

这让我在列出的第一个代码中遇到了问题。 pdfWriterStream 此时仅包含大约 800 个字节,当复制到 result 时,也仅获取这 800 个字节,而不是整个文件。

所以看起来document.Close() 将文件刷新到缓冲区,然后释放它。所以我想在将pdfWriterStream复制到result之前需要做一些操作,但是我不知道是什么。

【问题讨论】:

    标签: .net stream itext filestream memorystream


    【解决方案1】:

    首先,如果你想从一个方法返回一个MemoryStream对象,不要把它放在那个方法中的using子句中:当离开那个using块,流对象被释放,所以你的方法的调用者得到一个他不会高兴的封闭流。

    其次,如果您不希望在关联的Document 关闭时关闭PdfWriter 写入的流,只需将PdfWriter 属性CloseStream 设置为false

    因此:

    private Stream ModifyAndSavePDF(Stream sourceFile, string text)
    {
        var pdfWriterStream = new MemoryStream();
        var reader = new PdfReader(sourceFile);
        var document = new Document(reader.GetPageSizeWithRotation(1));
        var writer = PdfWriter.GetInstance(document, pdfWriterStream);
        writer.CloseStream = false;
        document.Open();
        for (var i = 1; i <= reader.NumberOfPages; i++)
        {
            document.NewPage();
            var importedPage = writer.GetImportedPage(reader, i);
            var contentByte = writer.DirectContent;
            //some more PDF editing stuff here. Not relevant.
        }
        document.Close();
        reader.Close();
    
        return pdfWriterStream;
    }
    

    顺便说一句,您不需要关闭PdfWriter,当关联的Document 关闭时,它会隐式关闭。

    另外,乍一看,您的方法看起来像是复制了一些原始 PDF 并对其应用了一些更改。通常(取决于您要应用的确切更改,也就是说)应该使用PdfStamper,而不是普通的PdfWriter

    【讨论】:

    • 是的。我知道在 using 语句中包含返回的流是一个糟糕的解决方案,但我的问题是当编写器/文档关闭时流已关闭,而不是在退出 using 块时关闭。但是CloseStream = false 是我的难题中缺少的部分,它解决了我的问题,非常感谢:)
    • 另外,感谢双方的提示。我不知道 PdfStamper,所以我绝对要去看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 2012-05-21
    相关资源
    最近更新 更多