Concatenate PDF documents using Aspose.PDF for .NET - Save cannot Mehtod access a closed stream

Hello,

I have a simple console application that concatenates documents, it worked very well under aspose.pdf 6.5.0.0. I recently upgraded to 6.7.0.0 and now I get this error:

Cannot access a closed Stream.
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.get_Position()
at ↔.↔.Read(Byte[] , Int32 , Int32 )
at :bangbang:.§.:smiling_face::slight_smile:(? , , Boolean , Int64& )
at :bangbang:.§.:smiling_face:.:smiling_face:(? , )
at ↓.:slight_smile:(? , , Boolean , Int64& )
at ↓.?.:smiling_face:(? , )
at :bangbang:.∟.:smiling_face::slight_smile:(? , , Boolean , Int64& )
at :bangbang:.∟.:smiling_face:.:smiling_face:(? streamWriter, pdfPrimitive, Int64& offset)
at ↓.:slight_smile:(? , , Boolean , Int64& )
at ↓.?.:smiling_face:(? streamWriter, pdfPrimitive, Int64& offset)
at ↑.∟.:smiling_face:(? , :bangbang: )
at ↓.?.?()
at ↓.?.:smiling_face:(Stream )
at ↓.?.:smiling_face:(Stream )
at Aspose.Pdf.Document.Save(Stream output)

If I change the aspose reference back to version 6.5 it works again.

Here is the code (basically adapted from the website example):


Public Function Concatenate(ByRef Pages As List(Of Byte())) As ConcatenatedDocument

Using CombinedDocument As New Aspose.Pdf.Document()

For Each p In Pages

Using Input As New MemoryStream(p)

CombinedDocument.Pages.Add(New Aspose.Pdf.Document(Input).Pages)

End Using

Next

Using OutStream As New MemoryStream(Pages.Sum(Function(x) x.Length))

CombinedDocument.Save(OutStream)

Return New ConcatenatedDocument With {.Document = OutStream.ToArray(), .PageCount = CombinedDocument.Pages.Count}

End Using

End Using

End Function

Any help would be greatly appreciated.

Thanks,

Hi Gray,

Thank you for using our products and sharing the sample code with us. I tried using your code to test your issue but due to missing variables, I was unable to replicate the scenario at my end. However, to exactly replicate your issue at our end, we would appreciate, if you create a sample application and post here to show us the issue. This will help us to regenerate the issue and get the cause of the issue soon.

We apologize for your inconvenience.

Thanks & Regards,

Hi Rashid,

The first post contains all required information to replicate this issue.

The Pages parameter is a list of byte arrays that represent pdf documents.

The definition of the return type of ConcatenatedDocument can be inferred from the return statement: Return New ConcatentatedDocument with {.Document = Outstream.ToArray(), .PageCount = CombinedDocument.Pages.Count}

Here is the entire console application’s code:

Imports System.IO

Module Main

Sub Main()

Try
Dim License As New Aspose.Pdf.License()
License.SetLicense(“Aspose.Pdf.lic”)

Dim PcDocument As Byte()
Dim Documents As New List(Of Byte())
PcDocument = ReadFromFileSystem(“Cover.pdf”)
Documents.Add(PcDocument)
Documents.Add(ReadFromFileSystem(“Attachment2.pdf”))
Documents.Add(ReadFromFileSystem(“Attachment2.pdf”))

Dim Result As ConcatenatedDocument = Concatenate(Documents)

Catch ex As Exception

Console.WriteLine(ex.Message)
Console.WriteLine(ex.StackTrace)

Finally

Console.WriteLine(“done.”)
Console.ReadLine()

End Try

End Sub

Public Function Concatenate(ByRef Pages As List(Of Byte())) As ConcatenatedDocument

Using CombinedDocument As New Aspose.Pdf.Document()

For Each p In Pages

Using Input As New MemoryStream(p)

CombinedDocument.Pages.Add(New Aspose.Pdf.Document(Input).Pages)

End Using

Next

Using OutStream As New MemoryStream(Pages.Sum(Function(x) x.Length))

CombinedDocument.Save(OutStream)

Return New ConcatenatedDocument With {.Document = OutStream.ToArray(), .PageCount = CombinedDocument.Pages.Count}

End Using

End Using

End Function

Private Sub WriteToFileSystem(ByVal FileName As String, ByRef Document As Byte())

Using OutputFileStream As New System.IO.FileStream(FileName, System.IO.FileMode.Create)

OutputFileStream.Write(Document, 0, Document.Length)

End Using

End Sub

Public Function ReadFromFileSystem(ByVal FileName As String) As Byte()

Using FileStream As New IO.FileStream(FileName, IO.FileMode.Open)

Using BinaryReader As New IO.BinaryReader(FileStream)

Return BinaryReader.ReadBytes(CInt(FileStream.Length))

End Using

End Using

End Function

End Module

Public Class ConcatenatedDocument

Public PageCount As Integer
Public Document As Byte()

Public Sub New()

PageCount = 0
Document = Nothing

End Sub

Public Sub New(ByVal PageCount As Integer, ByVal Document As Byte())

Me.PageCount = PageCount
Me.Document = Document

End Sub

End Class

Hi Gray,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Thank you for sharing the sample code.

I am able to generate your mentioned issue using your sample code. Your issue has been registered in our issue tracking system with issue id: PDFNEWNET-33372. You will be notified via this forum thread regarding any updates against this issue.

Sorry for the inconvenience,

Hi, we solved it temporarly, since we need the fix in 6.8 for some pdf-a issues, by sending in a memorystream of the document instead of a Apose.Pdf.Document in our "concatenate"-metod:

Initial code (with exception 6.8):
var mergedPdf = new Aspose.Pdf.Document();
... Settings some initial metadata
...Foreach PdfQueItem
var success = TryMergeQueItemToPdf(pdfQueItem, mergedPdf)
...Save result

private Boolean TryMergeQueItemToPdf(PdfQueItem pdfQueItem, Aspose.Pdf.Document mergePdf) {
... Loading filestream based on pdfQueItem
var pdfDoc = new Aspose.Pdf.Document(streamPdf);
mergedPDf.Pages.Add(pdfDoc.Pages);
... Disposing streamPdf etc
}

Modified code (working code 6.8):
var streamMergedPdf = new MemoryStream();
using (var mergedPdf = new Aspose.Pdf.Document())
{
... Settings some initial metadata
mergedPdf.Save(streamMergedPdf);
}
...Foreach PdfQueItem
var success = TryMergeQueItemToPdf(pdfQueItem, streamMergedPdf)
...Save result

private Boolean TryMergeQueItemToPdf(PdfQueItem pdfQueItem, MemoryStream streamMergedPdf) {
... Loading filestream based on pdfQueItem
var pdfDoc = new Aspose.Pdf.Document(streamPdf);
using (var mergedPDf = new Aspose.Pdf.Document(streamMergedPdf))
{
mergedPDf.Pages.Add(pdfDoc.Pages);
mergedPDf.Save();
}
... Disposing streamPdf etc
}

Performance-wise is this a bad temporary solution?

Hi Megnus,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

I am glad to know that you are able to temporarily resolve your issue. Now, regarding your performance question, I think as per your implementation, it will affect the performance a bit as you are loading the files first in memory stream before concatenating them. However, I think the major concern might be the memory consumption. If you have large files then it may consume a lot of memory. Also, regarding this issue, I have asked the development team to share an ETA. I will update you once I get a feedback from there side.

Sorry for the inconvenience,

Has this been fixed yet? Is there an ETA for fixing this (it has been almost 3 months now)?

Hi Gary,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Thank you for being patient and sorry for a delayed response.

After further analysis from our development team regarding your issue, they have shared the following feedback. As per your following code,

Using Input As New MemoryStream(p)
CombinedDocument.Pages.Add(New Aspose.Pdf.Document(Input).Pages)

End Using

After "End Using" object "Input As Memory" stream is destroyed which causes this problem. To overcome this, please don't use the "using" directive and please modify your code as mentioned below:

Public Function Concatenate(ByRef Pages As List(Of Byte())) As ConcatenatedDocument

Using CombinedDocument As New Aspose.Pdf.Document()

For Each p As Byte() In Pages

Dim Input As New MemoryStream(p)

CombinedDocument.Pages.Add(New Aspose.Pdf.Document(Input).Pages)

Next

CombinedDocument.Save("FinalMerged.pdf")

End Using

End Function

I have tested the above code with the latest version of Aspose.Pdf for .NET v7.0 and it works fine. Please try it and let us know if you still face any issue.

Sorry for the inconvenience,