In this article, we will use the Nutrient Web SDK, an external JavaScript PDF library, to preview PDF files in Power Pages.

Goal

Screenshot 2026-05-06 121351

Stepwise Implementation

1 - Create Custom Table

Screenshot 2026-05-06 121553

2 - Enable Web API Access to Table

Enable Web API access for the table so that the file content can be retrieved using JavaScript.

3 - Assign Permissions and Web Roles to Table

4 - Integrate Nutrient Web SDK (via CDN)

<script src="https://cdn.cloud.pspdfkit.com/[email protected]/nutrient-viewer.js"></script>

Code Section

1 - HTML

<script src="https://cdn.cloud.pspdfkit.com/[email protected]/nutrient-viewer.js"></script>

<div class="row sectionBlockLayout text-start" style="min-height: auto; padding: 8px;">
  <div style="width:100%; height:900px; overflow:hidden;">
    <div id="pspdfkit" style="width:100%; height:100%;"></div>
  </div>
</div>

2 - JS

(function (webapi, $) {
    function safeAjax(ajaxOptions) {
        var deferredAjax = $.Deferred();
        shell
            .getTokenDeferred()
            .done(function (token) {
                if (!ajaxOptions.headers) {
                    $.extend(ajaxOptions, {
                        headers: {
                            __RequestVerificationToken: token,
                        },
                    });
                } else {
                    ajaxOptions.headers["__RequestVerificationToken"] = token;
                }
                $.ajax(ajaxOptions)
                    .done(function (data, textStatus, jqXHR) {
                        validateLoginSession(data, textStatus, jqXHR, deferredAjax.resolve);
                    })
                    .fail(deferredAjax.reject);
            })
            .fail(function () {
                deferredAjax.rejectWith(this, arguments);
            });
        return deferredAjax.promise();
    }
    webapi.safeAjax = safeAjax;
})((window.webapi = window.webapi || {}), jQuery);
const id = "a4e2096b-6648-f111-bec6-6045bd09615c"
const containerId = "#pspdfkit";

document.addEventListener("DOMContentLoaded", () => {
    PreviewFile(id)
})
function PreviewFile(docId) {
    webapi.safeAjax({
        url: `/_api/cr399_doctables(${docId})/cr399_doc/$value`,
        type: "GET",
        xhrFields: {
            responseType: "blob"
        },
        success: function (blob) {
            if (blob) {
                loadNutrientPdfViewer(blob);
                console.log(blob)
            } else {
                console.log("Not loaded");
            }
        },
        error: function (err) {
            console.error(err);
        }
    });
}
url: `/_api/cr399_doctables(${docId})/cr399_doc/$value`,
let nutrientInstance = null;

function loadNutrientPdfViewer(blob) {
    const objectUrl = URL.createObjectURL(blob);

    window.NutrientViewer.unload("#pspdfkit");
    window.NutrientViewer.load({
        container: "#pspdfkit",
        document: objectUrl,
        initialViewState: new NutrientViewer.ViewState({
            sidebarMode: NutrientViewer.SidebarMode.THUMBNAILS
        })
    }).then((instance) => {
        nutrientInstance = instance;
        $(".loader").hide();
        URL.revokeObjectURL(objectUrl);
    }).catch(error => {
        console.error("Failed to load document:", error);
        URL.revokeObjectURL(objectUrl);
    });
}

Explantation

Conclusion