Create a new Document with a FileStream

I am trying to create a new Document using a FileStream to a new file, but Aspose.Pdf throws and exception with the message “Incorrect File Header”; I need the FileStream to use incremental saves because I’m merging a lot of documents and I don’t want to keep all of the Streams in scope until the final Save call.

await using var fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var document = new Document(fileStream);

@akeshgupta

Please use the code snippet like below for incremental saving:

using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);
{
 var document = new Document();
 document.Pages.Add();
 document.Save(fileStream);
}

Also, please note that you can simply call Document.Save() method (without any constructor) in order to save incremental changes at different steps of PDF generation. Please feel free to let us know in case you need more information.

This doesn’t appear to work with incremental saving. The following code results in a document with a single Page; changing the code to call Save(fileStream) multiple times throws an Exception for accessing a closed stream. Incremental Saves only appear to work when you pass the fileStream to the constructor, is this a limitation of Aspose or a Bug?

using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, 
FileAccess.ReadWrite);

var document = new Document();
document.Pages.Add();
document.Save(fileStream);

for(var i = 0; i < 5; i++) 
{
  document.Pages.Add();
  document.Save();
  //document.Save(fileStream); // throws an Exception
}

// document only has one blank page

The following code works as expected, but creating a document, saving it, then disposing it, just to open it again feels like a dirty hack.

var doc = new Document();
doc.Save(dataDir + "output.pdf");
doc.Dispose();

using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.Open, 
FileAccess.ReadWrite);
var document = new Document(fileStream);
document.Pages.Add();
document.Save();

for(var i = 0; i < 5; i++) 
{
  document.Pages.Add();
  document.Save();
}

// document now has multiple blank pages

@akeshgupta

Please note that the FileStream needs to remain open during the whole process of PDF generation. For example, please check the below code snippet: ​

// C# code
using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);
{
 var document = new Document();
 document.Pages.Add();
 document.Save(fileStream);
 document.Pages.Add();
 document.Save(fileStream);
}

Okay, it appears that I have oversimplified the example code; When using the parameterless constructor and you add the pages from another Document that was created using a MemoryStream, in the constructor, the streams are kept in the Document when calling document.Save(fileStream), but if you send the FileStream to the constructor of the initial Document, and you add the pages from another Document that was created using a MemoryStream in the constructor, the streams are not kept in the Document after calling document.Save(); Is this inconsistency in behavior a bug?

using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);

var document = new Document();
document.Pages.Add();
document.Save(fileStream);

for(var i = 0; i < 5; i++) 
{
  var reportBytes = GetReportBytes();
  // this stream is kept in the document after the call to Save() and goes out of scope
  // and throws a cannot access a closed stream Exception on the next iteration
  await using var memStream = new MemoryStream(reportBytes);
  var notice = new Document(memStream);  
  document.Pages.Add(notice.Pages);

  document.Save(fileStream); // throws an Exception
}

When using an existing Pdf file, the streams are no longer kept in the document after the call to Save(), so the code works as expected.

var doc = new Document();
doc.Save(dataDir + "output.pdf");
doc.Dispose();

using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);

var document = new Document(fileStream);
document.Pages.Add();
document.Save();

for(var i = 0; i < 5; i++) 
{
  var reportBytes = GetReportBytes(); // returns the bytes for a valid pdf file
  // this stream is not kept in the document after calling Save()
  await using var memStream = new MemoryStream(reportBytes);
  var notice = new Document(memStream);  
  document.Pages.Add(notice.Pages);

  document.Save();
}

@akeshgupta

Can you please share which .NET Framework version are you using? Also, if its possible, can you please provide a sample console application along with sample PDF that you are reading as second PDF to append the pages? It would help us in replicating the exact same scenario in our environment and address it accordingly.

I’m using .Net 6 MVC; I’m having trouble replicating the issue in the Console Application, but I’ll keep trying; is there a way to get a more usable stack trace to help identify the issue? Here is the Exception that is thrown.

System.ObjectDisposedException: Cannot access a closed Stream.
at System.IO.MemoryStream.get_Position()
at #=zD6zBtEdzJHcfRIvHaubdCj3bPnFXayL8VA==.Read(Byte[] #=zXXM9goE=, Int32 #=zWo98Y1o=, Int32 #=z_qHCqZI=)
at #=zw3RFHr8aDaHmCf9UcCPYlP$jYhktbR2X6g==.#=zNwv6vkQ=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Boolean #=zaG1LbsThwId_, Int64& #=zWo98Y1o=)
at #=zw3RFHr8aDaHmCf9UcCPYlP$jYhktbR2X6g==.#=zNwv6vkQ=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a)
at #=zLwyLu0TbsVSDCNa8Co2QkxlHQaKSfbK5kTrP1Ns=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Boolean #=zaG1LbsThwId_, Int64& #=zWo98Y1o=)
at #=zLwyLu0TbsVSDCNa8Co2QkxlHQaKSfbK5kTrP1Ns=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a)
at #=zjQRU3Ao6xrQglQDRuDAyxMY1PsKAI1C8PQ==.#=zNwv6vkQ=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Boolean #=zaG1LbsThwId_, Int64& #=zWo98Y1o=)
at #=zjQRU3Ao6xrQglQDRuDAyxMY1PsKAI1C8PQ==.#=zNwv6vkQ=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Int64& #=zWo98Y1o=)
at #=zLwyLu0TbsVSDCNa8Co2QkxlHQaKSfbK5kTrP1Ns=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Boolean #=zaG1LbsThwId_, Int64& #=zWo98Y1o=)
at #=zLwyLu0TbsVSDCNa8Co2QkxlHQaKSfbK5kTrP1Ns=.#=zpPz7S70=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zVAG$DdjlHTykOyjIWR019fOZIPAUssB6SA== #=zLRMTBIYsMT1a, Int64& #=zWo98Y1o=)
at #=zMnrIuVE7LGGqvgC2MoU9dRBKtUc5RkoySpUItbhOy2WGfkMTepWqROY=.#=zW2nVpN8=(#=zjg$kGjGZzVw0sjkQrRncALVe4GLYc0NCG4D7biLLbdwO #=zSILPxKo4IJx_, #=zyekuUAzwIV_7yR$8QN2gmMumOfqq90Fie6aZJ8g= #=zARoo5ho=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zOMK$jtHk8GJ1k50prgph7BmXrgibsAXyh19kHM9nh94C(Object #=zVkmR_wI=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=z74gdr6LUIjuqL6T$z0geL12cfNAO7zEWgukDVao=(MethodBase #=zVkmR_wI=, Boolean #=zCwIzx9Q=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zKs$0WKFzlpcO0oHBU84_aJiVHR2eU5Z2gi6PcvI=(#=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y= #=zVkmR_wI=, #=qWJchT92R96Q6acctPbzXOP8j89aZU$$_XNlaR$zcCgM= #=zCwIzx9Q=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=z0VZIzPVowscbrfbBXg==()
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=z6rqvdzkHYw0PwCPq9DaPdrVFdGBO1EmBOg==(Boolean #=zVkmR_wI=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zOMK$jtHk8GJ1k50prgph7BmXrgibsAXyh19kHM9nh94C(Object #=zVkmR_wI=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zKKYbQzscdwYuIbV57z7G2n4=()
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zlcyu2hpF7MnN4iQ6Umg2VGTNWk1f1X$l3qlNmkM=(Object #=zVkmR_wI=, UInt32 #=zCwIzx9Q=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=z6rqvdzkHYw0PwCPq9DaPdrVFdGBO1EmBOg==(Boolean #=zVkmR_wI=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zYAqg67fCL367flj8gfHSbCrv2ZlIPUGqwzP9YAI=()
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zCSL9gbyaa5NQY5XVj$jS3udiNiq54vrbRsCzPz8=(Object[] #=zVkmR_wI=, Type[] #=zCwIzx9Q=, Type[] #=zuevwSC8=, Object[] #=zx7Uf$6A=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zx0lqgdoiKlODEBjbe_7ToTs=(Stream #=zVkmR_wI=, String #=zCwIzx9Q=, Object[] #=zuevwSC8=, Type[] #=zx7Uf$6A=, Type[] #=zO0crUDw=, Object[] #=zxGTh1JE=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zd0T3JoqRzIFjle$6i4X1ONA=(Stream #=zVkmR_wI=, String #=zCwIzx9Q=, Object[] #=zuevwSC8=)
at #=qdvjf$2NVHNG_WicTUAgO8U0379HLIVs_d9O_Qv1eN_Y=.#=zqLADg051hEBE_icjrxTgVAg=(Stream #=zVkmR_wI=, String #=zCwIzx9Q=, Object[] #=zuevwSC8=)
at #=zNjmyzYNOUfZc3opeXG8xE71wRdUlPRTMWw==.#=zW2nVpN8=()
at #=z0RzJEoMmM1_Al4keQiMWujwzt4r9h8_Rgw==.#=zW2nVpN8=(Stream #=zUaptVZY=)
at #=zG5zgmaqMf_NWUoyosfDYJne5jola.#=zW2nVpN8=(Stream #=zUaptVZY=)
at Aspose.Pdf.Document.#=zrp75b8L6CejG(Stream #=zHVZrm8E=, SaveOptions #=zX307AXDwxp4e)
at Aspose.Pdf.Document.Save(Stream output)
at Application.Libraries.Process.FinalNoticeProcess.ThisDoesNotWork() in W:\Git\ClientName\cis\cis\Libraries\Process\FinalNoticeProcess.cs:line 183
at Application.Libraries.Process.FinalNoticeProcess.ThisDoesNotWork() in W:\Git\ClientName\cis\cis\Libraries\Process\FinalNoticeProcess.cs:line 183
at Application.Libraries.Process.FinalNoticeProcess.ThisDoesNotWork() in W:\Git\ClientName\cis\cis\Libraries\Process\FinalNoticeProcess.cs:line 190
at Application.Libraries.Process.FinalNoticeProcess.Execute(ProcessDetails processDetails, IProgress`1 progress) in W:\Git\ClientName\cis\cis\Libraries\Process\FinalNoticeProcess.cs:line 31
at Application.Libraries.Process.HostedProcessService.Process(ProcessDetails processDetails) in W:\Git\ClientName\cis\cis\Libraries\Process\HostedProcessService.cs:line 172

This appears to be an issue with version 21.8.0, it was fixed in 21.12.0, but our license only goes to 21.8.0…

@akeshgupta

Please note that .NET Core 6.0 was released on November 8, 2021, and its support was added in the 21.11 version of the API. Also, we always recommend using the latest version of the API as it has maximum support and fixes. Please try to upgrade your license and let us know in case you face any issues while using the latest version of the API.

As far as incremental saving is concerned, here is another way to do this:

// C# Code
using var fileStream = new FileStream(dataDir + "output.pdf", FileMode.OpenOrCreate, FileAccess.ReadWrite);
{
 var document = new Document();
 document.Pages.Add();
 document.Save(fileStream);
 document = new Document(fileStream);
 document.Pages.Add();
 document.Save();
}

Incremental update is used while Save() without parameter.

Thanks for the assistance, I’ll have to stick with the workaround since the client wasn’t happy with the initial cost of the license, I don’t think I’ll be able to convince them to pay again before their application goes live.

// the bug is also present in .Net 5.0

@akeshgupta

We are afraid that we cannot resolve any issue in the older versions of the API. The support is provided on the basis of latest available version. Also, the issues reported in older versions of the API are resolved in the latest and higher versions. Please feel free to let us know in case you need further assistance.