푸터 콘텐츠로 바로가기
IRONPDF 사용

Blazor Open PDF in new Tab with IronPDF: A Developers Tutorial

Opening PDF documents in a new browser tab is a common requirement for Blazor web applications. This tutorial demonstrates how to generate PDFs using IronPDF and display them in new tabs using JavaScript interop, providing users with a seamless document viewing experience. This example focuses on a Blazor Server version.

Prerequisites and Setup

Start by creating a new Blazor Server project in Visual Studio 2022. Install IronPDF via the NuGet Package Manager Console:

Install-Package IronPdf

Configure your IronPDF license in Program.cs to enable full functionality:

License.LicenseKey = "YOUR-LICENSE-KEY";
License.LicenseKey = "YOUR-LICENSE-KEY";
$vbLabelText   $csharpLabel

Understanding the Challenge

Blazor Server applications can't directly manipulate browser tabs from C# code on the server. The task of Blazor open PDF in new tab requires JavaScript InterOp (JS interop) to bridge server-side PDF generation with client-side window management.

IronPDF enables developers to generate high-quality PDF documents on the server, which can then be displayed using JavaScript's window.open() functionality. This approach means solving a common client-server problem in a net application.

Implementing JavaScript Functions in Your Blazor Web App

Add this JavaScript code to your _Host.cshtml file to handle PDF display in new browser tabs. This is the module responsible for client-side window management:

<script>
    window.openPdfInNewTab = function (pdfData, fileName) {
        // Convert base64 to blob
        const byteCharacters = atob(pdfData);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        // The type is 'application/pdf', not 'image/png' or 'image/jpg'
        const blob = new Blob([byteArray], { type: 'application/pdf' });
        // Create URL and open in new tab
        const blobUrl = URL.createObjectURL(blob);
        const newWindow = window.open(blobUrl, '_blank');
        if (newWindow) {
            newWindow.document.title = fileName || 'PDF Document';
        }
        // Clean up
        setTimeout(() => URL.revokeObjectURL(blobUrl), 100);
        return newWindow !== null;
    };
</script>
<script>
    window.openPdfInNewTab = function (pdfData, fileName) {
        // Convert base64 to blob
        const byteCharacters = atob(pdfData);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        // The type is 'application/pdf', not 'image/png' or 'image/jpg'
        const blob = new Blob([byteArray], { type: 'application/pdf' });
        // Create URL and open in new tab
        const blobUrl = URL.createObjectURL(blob);
        const newWindow = window.open(blobUrl, '_blank');
        if (newWindow) {
            newWindow.document.title = fileName || 'PDF Document';
        }
        // Clean up
        setTimeout(() => URL.revokeObjectURL(blobUrl), 100);
        return newWindow !== null;
    };
</script>
$vbLabelText   $csharpLabel

The window.openPdfInNewTab JavaScript function is crucial for solving the challenge of opening a new tab from the server. It accepts the PDF data as a Base64 string from the Blazor server and client-side code converts it into a binary Blob object.

This blob is then used to create a temporary URL, which is finally passed to window.open(blobUrl, '_blank') to force the browser to open the PDF in a new tab.

Creating the Blazor Component

Create a new Razor component that generates PDFs and opens them in new tabs. This serves as the main template for the solution:

@page "/pdf-viewer"
@using IronPDF @inject IJSRuntime JS
<h3>Open PDF in New Tab</h3>
<div class="mb-3">
    <label>Enter URL:</label>
</div>
<button class="btn btn-primary" @onclick="GenerateAndOpenPdf"
        disabled="@isProcessing">
    @if (isProcessing)
    {
        <span>Generating PDF...</span>
    }
    else
    {
        <span>Generate and Open PDF</span>
    }
</button>
@if (!string.IsNullOrEmpty(errorMessage))
{
    <div class="alert alert-danger mt-3">@errorMessage</div>
}
@code {
    private string targetUrl = "https://ironpdf.com";
    private bool isProcessing = false;
    private string errorMessage = "";
    private async Task GenerateAndOpenPdf()
    {
        isProcessing = true;
        errorMessage = "";
        try
        {
            // Configure Chrome PDF renderer. Note the rendering details
            var renderer = new ChromePdfRenderer
            {
                RenderingOptions = new ChromePdfRenderOptions
                {
                    MarginTop = 10,
                    MarginBottom = 10,
                    MarginLeft = 10,
                    MarginRight = 10,
                    EnableJavaScript = true,
                    RenderDelay = 500
                }
            };
            // Generate PDF from URL
            var pdfDocument = await Task.Run(() =>
                renderer.RenderUrlAsPdf(targetUrl));
            // Convert to base64
            byte[] pdfBytes = pdfDocument.BinaryData;
            string base64Pdf = Convert.ToBase64String(pdfBytes);
            // Open in new tab via JS interop. We run this call to open the PDF
            bool success = await JS.InvokeAsync<bool>("openPdfInNewTab",
                base64Pdf, $"Document_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
            if (!success)
            {
                // Giving the user an understandable error is key
                errorMessage = "Pop-up blocked. Please allow pop-ups for this site.";
            }
        }
        catch (Exception ex)
        {
            errorMessage = $"Error: {ex.Message}";
        }
        finally
        {
            isProcessing = false;
        }
    }
}
@page "/pdf-viewer"
@using IronPDF @inject IJSRuntime JS
<h3>Open PDF in New Tab</h3>
<div class="mb-3">
    <label>Enter URL:</label>
</div>
<button class="btn btn-primary" @onclick="GenerateAndOpenPdf"
        disabled="@isProcessing">
    @if (isProcessing)
    {
        <span>Generating PDF...</span>
    }
    else
    {
        <span>Generate and Open PDF</span>
    }
</button>
@if (!string.IsNullOrEmpty(errorMessage))
{
    <div class="alert alert-danger mt-3">@errorMessage</div>
}
@code {
    private string targetUrl = "https://ironpdf.com";
    private bool isProcessing = false;
    private string errorMessage = "";
    private async Task GenerateAndOpenPdf()
    {
        isProcessing = true;
        errorMessage = "";
        try
        {
            // Configure Chrome PDF renderer. Note the rendering details
            var renderer = new ChromePdfRenderer
            {
                RenderingOptions = new ChromePdfRenderOptions
                {
                    MarginTop = 10,
                    MarginBottom = 10,
                    MarginLeft = 10,
                    MarginRight = 10,
                    EnableJavaScript = true,
                    RenderDelay = 500
                }
            };
            // Generate PDF from URL
            var pdfDocument = await Task.Run(() =>
                renderer.RenderUrlAsPdf(targetUrl));
            // Convert to base64
            byte[] pdfBytes = pdfDocument.BinaryData;
            string base64Pdf = Convert.ToBase64String(pdfBytes);
            // Open in new tab via JS interop. We run this call to open the PDF
            bool success = await JS.InvokeAsync<bool>("openPdfInNewTab",
                base64Pdf, $"Document_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
            if (!success)
            {
                // Giving the user an understandable error is key
                errorMessage = "Pop-up blocked. Please allow pop-ups for this site.";
            }
        }
        catch (Exception ex)
        {
            errorMessage = $"Error: {ex.Message}";
        }
        finally
        {
            isProcessing = false;
        }
    }
}
$vbLabelText   $csharpLabel

This code block defines the main interactive page. The Razor markup creates a simple user interface with a URL input field and a button. The C# @code block handles the logic: when the button is clicked, it uses a ChromePdfRenderer instance to generate the PDF from the user's provided URL.

It then converts the resulting PDF byte array into a Base64 string and uses @inject IJSRuntime JS to call the JavaScript function, opening the document for the user.

UI Output

Blazor Open PDF in new Tab with IronPDF: A Developers Tutorial: Image 1 - Example basic UI

Output with PDF Opened in New Tab

Blazor Open PDF in new Tab with IronPDF: A Developers Tutorial: Image 2 - First PDF opened in new tab

Working with Dynamic HTML Content

For generating PDFs from dynamic content instead of URLs, modify your approach to use RenderHtmlAsPdf:

private async Task GenerateFromHtml()
{
    // Define CSS styles inside the HTML string for structure and appearance.
    string htmlContent = $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: Arial; padding: 20px; }}
                h1 {{ color: #2c3e50; }}
            </style>
        </head>
        <body>
            <h1>{documentTitle}</h1>
            <p>{documentContent}</p>
            <div>Generated: {DateTime.Now}</div>
        </body>
        </html>";
    var renderer = new ChromePdfRenderer();
    var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
    byte[] pdfBytes = pdfDocument.BinaryData;
    await JS.InvokeVoidAsync("openPdfInNewTab",
        Convert.ToBase64String(pdfBytes), "dynamic.pdf");
}
private async Task GenerateFromHtml()
{
    // Define CSS styles inside the HTML string for structure and appearance.
    string htmlContent = $@"
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body {{ font-family: Arial; padding: 20px; }}
                h1 {{ color: #2c3e50; }}
            </style>
        </head>
        <body>
            <h1>{documentTitle}</h1>
            <p>{documentContent}</p>
            <div>Generated: {DateTime.Now}</div>
        </body>
        </html>";
    var renderer = new ChromePdfRenderer();
    var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
    byte[] pdfBytes = pdfDocument.BinaryData;
    await JS.InvokeVoidAsync("openPdfInNewTab",
        Convert.ToBase64String(pdfBytes), "dynamic.pdf");
}
$vbLabelText   $csharpLabel

The GenerateFromHtml method demonstrates how IronPDF can generate a PDF from dynamically generated HTML markup instead of an existing URL. It constructs a full HTML string containing a heading, content, and dynamic data. The answer to dynamic content generation is the RenderHtmlAsPdf method.

Updated Blazor Server UI

Blazor Open PDF in new Tab with IronPDF: A Developers Tutorial: Image 3 - Updated example UI for your Server project

PDF Opened in New Browser Tab

Blazor Open PDF in new Tab with IronPDF: A Developers Tutorial: Image 4 - Example dynamic PDF created and then opened in new tab

Handling Common Issues

Cross-Browser Compatibility

Different browsers handle blob URLs differently. Test your implementation across Chrome, Firefox, Edge, and Safari to ensure consistent behavior.

Large Files

For large PDF documents, consider implementing server-side caching to improve performance:

services.AddMemoryCache();
// Cache generated PDFs to avoid regeneration
services.AddMemoryCache();
// Cache generated PDFs to avoid regeneration
$vbLabelText   $csharpLabel

Navigation Alternatives

Besides JavaScript interop, you can serve PDFs through static file middleware and use standard HTML anchor tags for an alternative navigate option:

<a href="/pdfs/document.pdf" target="_blank">Open PDF</a>
<a href="/pdfs/document.pdf" target="_blank">Open PDF</a>
$vbLabelText   $csharpLabel

This approach works well for pre-generated PDFs but lacks the dynamic generation capabilities of the JS InterOp method.

Best Practices

  1. Error Handling: Always wrap PDF generation in try-catch blocks and provide meaningful error messages to users when a problem occurs.
  2. Performance: Use async/await patterns to prevent UI blocking during PDF generation.
  3. User Experience: Show loading indicators during generation and handle pop-up blocker scenarios gracefully.
  4. DOM Manipulation: Remember that C# on the server cannot manipulate the client's DOM directly; this is why JS InterOp is essential. You don't need to manually set the height or width of the new window, as the browser handles the PDF viewer.
  5. Security: Validate and sanitize user input before generating PDFs

Conclusion

Combining IronPDF's powerful PDF generation capabilities with Blazor's JavaScript InterOp provides a robust solution for opening PDFs in new browser tabs. This approach enables developers to create dynamic, professional PDF documents that seamlessly integrate with modern Blazor applications built on .NET technology by Microsoft.

Ready to implement PDF functionality in your Blazor project? Start your free IronPDF trial today. The trial includes full functionality without watermarks and comprehensive support to ensure your success.

자주 묻는 질문

Blazor를 사용하여 새 탭에서 PDF를 열려면 어떻게 해야 하나요?

Blazor를 사용하여 IronPDF로 PDF를 생성하고 JavaScript 인터롭을 활용하여 새 탭에서 PDF를 표시하면 새 탭에서 PDF를 열 수 있습니다. 이 접근 방식은 문서를 볼 때 원활한 사용자 경험을 보장합니다.

Blazor의 JavaScript 인터롭이란 무엇인가요?

Blazor의 JavaScript 상호 운용을 사용하면 Blazor 애플리케이션에서 .NET 코드에서 JavaScript 함수를 호출하거나 그 반대로 호출할 수 있습니다. 이는 새 탭에서 PDF를 여는 것과 같이 JavaScript가 브라우저별 작업을 처리할 수 있는 작업에 유용합니다.

Blazor에서 PDF를 생성할 때 IronPDF를 사용해야 하는 이유는 무엇인가요?

IronPDF는 Blazor 애플리케이션에서 PDF를 생성하기 위한 효율적인 도구입니다. 이 도구는 원활한 PDF 생성 및 조작을 가능하게 하는 강력한 기능을 제공하며, Blazor의 JavaScript 인터롭과 쉽게 통합하여 문서 처리 기능을 향상시킬 수 있습니다.

IronPDF는 Blazor 서버와 호환되나요?

예, IronPDF는 Blazor 서버와 완벽하게 호환됩니다. PDF를 생성하고 관리하는 데 사용할 수 있으며, JavaScript 인터롭을 사용하여 새 탭에서 열 수 있습니다.

Blazor 애플리케이션에서 새 탭에서 PDF를 열면 어떤 이점이 있나요?

새 탭에서 PDF를 열면 사용자가 현재 페이지에서 벗어나지 않고도 문서를 볼 수 있어 사용자 경험이 향상됩니다. IronPDF와 JavaScript 인터롭에서 지원하는 이 방법은 보다 인터랙티브하고 중단 없는 브라우징 세션을 보장합니다.

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.