将MemoryStream用于iTextSharp

时间:2018-11-28 11:20:22

标签: .net stream itext filestream memorystream

我有以下问题。

此代码可以正常工作

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之前需要做一些操作,但是我不知道要做什么。

1 个答案:

答案 0 :(得分:1)

首先,如果要从方法中返回MemoryStream对象,请不要将其放在该方法的using子句中:在using块中放置了流对象,因此您的方法的调用者将获得一个封闭的流,他不会对此感到满意。

第二,如果您不希望在关联的PdfWriter关闭时关闭Document写入的流,只需将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