DEV Community

IronSoftware
IronSoftware

Posted on

Work with PDF MemoryStream in C#

Our API returned PDFs as byte arrays. We needed to process them without hitting the file system. Temporary files cluttered our Azure App Service. Disk I/O became a bottleneck.

MemoryStream solved this. Here's how to load and save PDFs in memory.

How Do I Load a PDF from MemoryStream?

Pass the byte array to the PDF Document constructor:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

byte[] pdfBytes = GetPdfFromDatabase(); // Your data source

var pdf = PdfDocument.FromBinary(pdfBytes);

// Modify the PDF
pdf.MetaData.Title = "Updated Document";

pdf.SaveAs("output.pdf");
Enter fullscreen mode Exit fullscreen mode

The PDF loads entirely in memory. No temporary files created.

Why Use MemoryStream for PDFs?

Performance: Avoids disk I/O overhead
Serverless compatibility: AWS Lambda and Azure Functions restrict file system access
Security: Temporary files can leak sensitive data
Scalability: Reduces disk space constraints in containerized environments
API integration: Direct handling of PDFs from HTTP responses

I use MemoryStream for all PDF processing in our Kubernetes cluster. No file system dependency.

How Do I Save a PDF to MemoryStream?

Use ToBytes() or Stream():

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice</h1>");

// Get as byte array
byte[] pdfBytes = pdf.BinaryData;

// Or get as Stream
using var stream = pdf.Stream;
Enter fullscreen mode Exit fullscreen mode

Send pdfBytes to a database, upload to blob storage, or return from an API.

Can I Load PDFs from Network Streams?

Yes. Read the stream into a byte array first:

using var httpClient = new HttpClient();
var response = await httpClient.GetAsync("https://example.com/document.pdf");

byte[] pdfData = await response.Content.ReadAsByteArrayAsync();

var pdf = PdfDocument.FromBinary(pdfData);
Enter fullscreen mode Exit fullscreen mode

This works for any HTTP endpoint returning PDF content.

How Do I Load PDFs from a Database?

Assuming your database stores PDFs as varbinary or BLOB:

// Example with Entity Framework
var document = await dbContext.Documents
    .FirstOrDefaultAsync(d => d.Id == documentId);

var pdf = PdfDocument.FromBinary(document.PdfData);

// Modify and save back
pdf.MetaData.Author = "Updated Author";
document.PdfData = pdf.BinaryData;
await dbContext.SaveChangesAsync();
Enter fullscreen mode Exit fullscreen mode

No file system interaction. PDFs stay in memory throughout the pipeline.

Can I Convert FileStream to PdfDocument?

Yes, read the stream:

using var fileStream = File.OpenRead("existing.pdf");
using var memoryStream = new MemoryStream();

await fileStream.CopyToAsync(memoryStream);
byte[] pdfBytes = memoryStream.ToArray();

var pdf = PdfDocument.FromBinary(pdfBytes);
Enter fullscreen mode Exit fullscreen mode

Or use PdfDocument.FromFile() if you have file access:

var pdf = PdfDocument.FromFile("existing.pdf");
Enter fullscreen mode Exit fullscreen mode

How Do I Upload PDFs to Azure Blob Storage?

Generate PDF in memory and upload directly:

using Azure.Storage.Blobs;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");

var blobClient = new BlobClient(connectionString, containerName, "report.pdf");

using var stream = new MemoryStream(pdf.BinaryData);
await blobClient.UploadAsync(stream, overwrite: true);
Enter fullscreen mode Exit fullscreen mode

No temporary file needed. PDF goes directly from memory to blob storage.

Can I Return PDFs from ASP.NET Core APIs?

Yes, use FileStreamResult or FileContentResult:

[HttpGet("download")]
public IActionResult DownloadPdf()
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf("<h1>Document</h1>");

    return File(pdf.BinaryData, "application/pdf", "document.pdf");
}
Enter fullscreen mode Exit fullscreen mode

The client receives the PDF as a download. No server-side file created.

How Do I Merge PDFs from Multiple Sources?

Load each PDF from memory and merge:

byte[] pdf1Bytes = await GetPdfFromApi1();
byte[] pdf2Bytes = await GetPdfFromDatabase();

var pdf1 = PdfDocument.FromBinary(pdf1Bytes);
var pdf2 = PdfDocument.FromBinary(pdf2Bytes);

var merged = PdfDocument.Merge(pdf1, pdf2);

byte[] mergedBytes = merged.BinaryData;
Enter fullscreen mode Exit fullscreen mode

All operations happen in memory.

What's the Performance Impact?

Memory usage: PDFs load entirely into RAM. A 10MB PDF consumes ~10MB memory.
Speed: MemoryStream is faster than file I/O (no disk seeks)
Garbage collection: Large PDFs increase GC pressure. Dispose objects promptly.

For large PDFs (>100MB), consider streaming directly to disk if memory is constrained.

I process thousands of PDFs daily this way. Works well for documents under 50MB.

How Do I Handle Large PDFs?

For very large files, use streaming:

var pdf = PdfDocument.FromFile("large.pdf");

// Process page by page if possible
for (int i = 0; i < pdf.PageCount; i++)
{
    var singlePage = pdf.CopyPage(i);
    // Process this page
}
Enter fullscreen mode Exit fullscreen mode

Or enable streaming mode if your PDF library supports it.

Can I Load PDFs from Base64 Strings?

Yes, decode first:

string base64Pdf = "JVBERi0xLjQKJeLjz9MK..."; // Base64 encoded PDF

byte[] pdfBytes = Convert.FromBase64String(base64Pdf);
var pdf = PdfDocument.FromBinary(pdfBytes);
Enter fullscreen mode Exit fullscreen mode

Common when receiving PDFs from JSON APIs.

How Do I Cache PDFs in Memory?

Use MemoryCache for temporary storage:

using Microsoft.Extensions.Caching.Memory;

private readonly IMemoryCache _cache;

public byte[] GetOrGeneratePdf(string cacheKey)
{
    if (!_cache.TryGetValue(cacheKey, out byte[] pdfBytes))
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Cached Document</h1>");

        pdfBytes = pdf.BinaryData;

        _cache.Set(cacheKey, pdfBytes, TimeSpan.FromMinutes(30));
    }

    return pdfBytes;
}
Enter fullscreen mode Exit fullscreen mode

Avoid re-generating the same PDF repeatedly.

What About Concurrent Access?

MemoryStream and byte arrays are thread-safe for read operations. For concurrent writes, use locking or immutable patterns:

private static readonly object _lock = new object();

lock (_lock)
{
    var pdf = PdfDocument.FromBinary(sharedBytes);
    // Modify safely
}
Enter fullscreen mode Exit fullscreen mode

Or create separate PDF instances per thread.

Do I Need to Dispose MemoryStream?

IronPDF handles disposal internally. If you create your own streams:

using (var stream = new MemoryStream(pdfBytes))
{
    // Work with stream
}
// Disposed automatically
Enter fullscreen mode Exit fullscreen mode

Use using statements or await using for async scenarios.


Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)