【问题标题】:Cannot access a closed Stream. When using PDFReader无法访问已关闭的 Stream。使用 PDFReader 时
【发布时间】:2020-03-09 19:04:15
【问题描述】:

我有这个文件,它是一个 Stream:

 var streamFile = await graphClient.Me.Drive.Items["id"].Content.Request().GetAsync();

现在我正在尝试使用 PdfReader 和 PdfStamper 来设置字段,如下所示:

MemoryStream outFile = new MemoryStream();

PdfReader pdfReader = new PdfReader(streamFile);
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
AcroFields fields = pdfStamper.AcroFields;

fields.SetField("Full_Names", "JIMMMMMMAYYYYY");

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

但是当我尝试这样做时,我得到了这个错误:

无法访问已关闭的 Stream。

在这一行:

pdfReader.Close();

我做错了什么?

更新

我试过了,还是一样的错误:

using (MemoryStream outFile = new MemoryStream())
{

    var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();

    using (PdfReader pdfReader = new PdfReader(streamFile))
    {
        using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile))
        {

            AcroFields fields = pdfStamper.AcroFields;
            fields.SetField("Full_Names", "JIMMMMMMAYYYYY");

        }
    }

    outFile.Position = 0;

    await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(outFile);

}

更新

我已经尝试将 Stream 转换为这样的字节:

var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();

            byte[] buffer = new byte[16 * 1024];

            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = streamFile.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }

                using (PdfReader pdfReader = new PdfReader(ms.ToArray()))
                {
                    using (PdfStamper pdfStamper = new PdfStamper(pdfReader, ms))
                    {

                        AcroFields fields = pdfStamper.AcroFields;
                        fields.SetField("Full_Names", "JIMMMMMMAYYYYY");

                    }
                }

                await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(ms);

            }

同样的结果...无法在这一行访问已关闭的 Stream:

await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(ms);

PutAsync 也需要一个 Stream

所以当我这样做时:

var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();

await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(streamFile);

上传文件没问题。所以我确实认为问题在于尝试使用 iTextSharp 编辑 PDF。

【问题讨论】:

  • 现在哪里出错了?如果它在 outFile.Position = 0; 上,那么您可以删除该行。
  • 它在这条线上。 await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync(outFile);
  • OK 所以你在outFile 流关闭后使用它。我会尝试在 PdfStamper using 块中移动这两行,或者创建一个新流来重新读取输出文件。
  • 为防止 iText 关闭您的流,请尝试将该流中的所有字节读取到 byte[] 并从该 byte[] 初始化 PdfReader
  • @mkl 我该怎么做?

标签: c# asp.net model-view-controller itext


【解决方案1】:

您可以尝试以下方法:

 var streamFile = await graphClient.Me.Drive.Items["item-id"].Content.Request().GetAsync();

  byte[] buffer = new byte[16 * 1024];

  try
  {
    PdfReader pdfReader = null;
    PdfStamper pdfStamper = null;

    using (MemoryStream ms = new MemoryStream())
    {
      int read;
      while ((read = streamFile.Read(buffer, 0, buffer.Length)) > 0)
      {
        ms.Write(buffer, 0, read);
      }

      pdfReader = new PdfReader(ms.ToArray());

      pdfStamper = new PdfStamper(pdfReader, ms);


        AcroFields fields = pdfStamper.AcroFields;
      fields.SetField("Full_Names", "JIMMMMMMAYYYYY");




      await graphClient.Me.Drive.Items["item-id"].ItemWithPath("NewDocument-2.pdf").Content.Request().PutAsync<DriveItem>(ms);

    }
  }
  finally
  {
    if (pdfReader != null) pdfReader.Dispose();
    if (pdfStamper != null) pdfStamper.Dispose();
  }

等待完成后处理 pdfReader 和 pdfStamper。

【讨论】:

    【解决方案2】:

    在我的例子中,我想在内存中创建文档并在创建文档后添加 WaterMark,但没有将物理文件保存为中间步骤(效果很好,但几乎没有那么整洁)。

    public byte[] AsArray(List<DocumentData> list)
    {
        MemoryStream streamIn = new MemoryStream(); // Set the initial stream for the document
        MemoryStream streamOut = new MemoryStream(); // Set the result output stream
        PdfWriter writer = new PdfWriter(streamIn); // create the writer for document
    
        CreateDocument(writer, list); // Method where the document actually get's made
    
        // Now the tricky bit
        // Translate the `streamIn` (that now contains the document stream) into a PdfReader
        // use the byte[] from streamIn to create a new MemoryStream()
        PdfReader reader = new PdfReader(new MemoryStream(streamIn.ToArray()));
        writer = new PdfWriter(streamOut); // Set the writer stream to be the streamOut
    
        SetWaterMark(reader, writer); // Method to read through the document and add watermarks
    
        return streamOut.ToArray();
    }
    

    嘿,Presto,成功了!

    【讨论】:

      猜你喜欢
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 2013-07-15
      • 2020-08-05
      相关资源
      最近更新 更多