Need to serve a PDF from an API without saving it to disk? Work with PDF bytes in memory for database storage? Here's how to convert PDFs to MemoryStream and byte arrays in C#.
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new [ChromePdfRenderer](https://ironpdf.com/blog/videos/how-to-render-an-html-file-to-pdf-in-csharp-ironpdf/)();
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1234</h1>");
// Get as MemoryStream
Stream pdfStream = pdf.Stream;
// Or get as byte array
byte[] pdfBytes = pdf.BinaryData;
Two properties. No file I/O. Your PDF lives entirely in memory.
Why Would I Need a PDF in Memory?
Plenty of real-world scenarios require PDFs without touching the filesystem:
Web APIs - Return a PDF from a controller action without creating temp files
Database storage - Store PDF binary data in SQL Server's varbinary column
Email attachments - Attach PDFs to emails using System.Net.Mail
Cloud functions - Azure Functions and AWS Lambda have read-only filesystems
Microservices - Pass PDFs between services via message queues
In all these cases, writing to disk and reading back wastes time and creates cleanup headaches.
How Do I Get a PDF as a MemoryStream?
IronPDF exposes the rendered PDF through its Stream property:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<body>
<h1>Quarterly Report</h1>
<p>Q4 2024 Results</p>
</body>
</html>");
Stream memoryStream = pdf.Stream;
// The stream is positioned at the beginning
// Ready for immediate use
The Stream property returns a System.IO.Stream that you can pass directly to any method expecting a stream—no casting or conversion needed.
How Do I Get a PDF as a Byte Array?
For scenarios where you need raw bytes (database storage, Base64 encoding), use BinaryData:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello</h1>");
byte[] pdfBytes = pdf.BinaryData;
// Store in database
await connection.ExecuteAsync(
"INSERT INTO Documents (Content) VALUES (@Content)",
new { Content = pdfBytes });
BinaryData gives you the complete PDF file as a byte[]. This is the same data you'd get from File.ReadAllBytes() on a saved PDF—just without the file.
How Do I Return a PDF from an ASP.NET Core API?
The most common use case. Here's a controller that generates and returns a PDF without any disk access:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult GetInvoice(int id)
{
var invoice = GetInvoiceData(id);
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice));
return File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf");
}
}
The File() method accepts a byte array. The third parameter sets the download filename. Your users get a properly-named PDF download with zero temp files created.
How Do I Load an Existing PDF into Memory?
Sometimes you need to read an existing PDF file into memory for processing:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
// From a file path
var pdf = PdfDocument.FromFile("existing.pdf");
byte[] bytes = pdf.BinaryData;
Stream stream = pdf.Stream;
// From a URL
var pdfFromUrl = PdfDocument.FromUrl("https://example.com/document.pdf");
byte[] urlBytes = pdfFromUrl.BinaryData;
This is useful when you need to merge, watermark, or otherwise modify an existing PDF before serving it.
How Do I Convert a MemoryStream Back to a PDF?
Going the other direction—from bytes or stream back to a PdfDocument:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
// From byte array
byte[] pdfBytes = GetBytesFromDatabase();
var pdf = new PdfDocument(pdfBytes);
// From stream
Stream pdfStream = GetStreamFromSomewhere();
var pdfFromStream = new PdfDocument(pdfStream);
// Now you can manipulate it
pdf.ApplyWatermark("<h2>CONFIDENTIAL</h2>");
byte[] watermarkedBytes = pdf.BinaryData;
The PdfDocument constructor accepts both byte[] and Stream. Once loaded, you have full access to all manipulation methods.
What About Memory Management?
PDFs can be large. A 100-page document might consume 50MB or more. Keep these practices in mind:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
// Good: Dispose when done
using (var pdf = renderer.RenderHtmlAsPdf(html))
{
var bytes = pdf.BinaryData;
// Use bytes...
} // PDF resources freed here
// Better for large files: Stream directly
[HttpGet("{id}")]
public IActionResult GetLargeReport(int id)
{
var pdf = GenerateLargeReport(id);
// Stream property avoids copying the entire PDF into a new byte[]
return File(pdf.Stream, "application/pdf", "report.pdf");
}
Using pdf.Stream is slightly more memory-efficient than pdf.BinaryData because it avoids an extra array allocation. For small PDFs, the difference is negligible. For multi-megabyte documents, it adds up.
How Do I Send a PDF as an Email Attachment?
A common workflow—generate a PDF and email it:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
var message = new MailMessage("from@company.com", "customer@example.com")
{
Subject = "Your Invoice",
Body = "Please find your invoice attached."
};
// Create attachment from memory stream
var attachment = new Attachment(
new MemoryStream(pdf.BinaryData),
"invoice.pdf",
"application/pdf");
message.Attachments.Add(attachment);
using var smtp = new SmtpClient("smtp.company.com");
await smtp.SendMailAsync(message);
The Attachment constructor accepts a Stream. Wrap your BinaryData in a MemoryStream and you're done.
How Do I Store PDFs in Azure Blob Storage?
Cloud storage APIs work with streams and bytes:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(reportHtml);
var blobClient = containerClient.GetBlobClient($"reports/{reportId}.pdf");
// Upload directly from stream
await blobClient.UploadAsync(
new MemoryStream(pdf.BinaryData),
overwrite: true);
No temp files. The PDF goes from render to cloud in one step.
Quick Reference: Stream vs BinaryData
| Property | Returns | Best For |
|---|---|---|
Stream |
System.IO.Stream |
Streaming responses, minimal memory |
BinaryData |
byte[] |
Database storage, email attachments, Base64 |
Both properties access the same underlying PDF data. Choose based on what the consuming API expects.
The key insight: modern PDF libraries shouldn't require filesystem access. When you generate a PDF, you should have immediate access to its bytes. Everything else—saving, streaming, storing—is just routing those bytes to the right destination.
For more details on working with PDFs in memory, see the full IronPDF MemoryStream documentation.
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)