Delete PDF Pages

This demo uses the PDF Document API to delete pages from a PDF document. Switch to the target page and click  Delete current page.

1 of 8
Delete current page
@model AspNetCoreDemos.OfficeFileAPI.PdfPreviewModel

<img id="previewImage" src="@Url.Action(Model.PreviewDocumentAction, Model.ControllerName)" class="preview-image-bordered @(Model.IsViewWithoutSidePanel ? "preview-image-without-side-panel" : "preview-image-with-side-panel")" />

<script type="text/javascript">
    PdfPreview = {
        basePath: '@Url.Action(Model.PreviewDocumentAction, Model.ControllerName)',
        Update: function (param) {
            var iframeElement = document.getElementById("previewImage");
            if (!iframeElement)
                return;
            var additionalParams = "&" + new Date().valueOf();
            if (param)
                additionalParams = param;
            iframeElement.src = this.basePath + "?" + additionalParams;
        }
    };
</script>
@model AspNetCoreDemos.OfficeFileAPI.PdfPageDeletionModel
@using DevExtreme.AspNet.Mvc

@using (Html.BeginForm("PdfDeleteCurrentPage", "SplitMerge", FormMethod.Post)) {
    @Html.HiddenFor(model => model.PageCount)
    @Html.HiddenFor(model => model.PageIndex)

    <div class="demo-nav">
        <div class="demo-nav-item">
            @(Html.DevExtreme().Button()
                               .ID("PreviousPageButton")
                               .Icon("chevronprev")
                               .OnClick("PreviousPage")
                               .Disabled(true)
            )
        </div>
        <div class="demo-nav-item">
            <span id="pageIndexField">
                @(Model.PageIndex + 1)
            </span>
            of
            <span id="pageCountField">
                @Model.PageCount
            </span>
        </div>
        <div class="demo-nav-item">
            @(Html.DevExtreme().Button()
                               .ID("NextPageButton")
                               .Icon("chevronnext")
                               .OnClick("NextPage")
            )
        </div>
        <div class="demo-nav-item">
            @(Html.DevExtreme().Button()
                               .ID("ButtonDeletePage")
                               .Text("Delete current page")
                               .Type(ButtonType.Default)
                               .StylingMode(ButtonStylingMode.Contained)
                               .OnClick("DeletePage")
            )
        </div>
    </div>

    <div class="demo-preview-border">
        @(Html.DevExtreme().ScrollView()
                           .ID("scrollview")
                           .ScrollByContent(true)
                           .ScrollByThumb(true)
                           .ShowScrollbar(ShowScrollbarMode.OnHover)
                           .Direction(ScrollDirection.Both)
                           .Height("580px")
                           .Content(@<text>
                            <div id="scrollview-content">
                                @await Html.PartialAsync("PdfFileView", Model.PreviewModel)
                            </div>
                           </text>)
        )
    </div>

    <script type="text/javascript">
        function DeletePage() {
            SetDisable('#ButtonDeletePage', true);
            $.ajax({
                type: "POST",
                url: '@Url.Action("PdfDeleteCurrentPage", "SplitMerge")',
                data: { pageNumber: $('#PageIndex').val() },
                success: function () {
                    SetDisable('#ButtonDeletePage', false);
                    PageDeleted();
                }
            });
        }

        function UpdatePreview(pageIndex) {
            PdfPreview.Update("PageIndex=" + pageIndex + "&" + new Date().valueOf());
        }
        function SetDisable(button, disabled) {
            $(button).dxButton("instance").option("disabled", disabled);
        }
        function PageDeleted() {
            var pageCount = parseInt($('#PageCount').val()) - 1;

            if (pageCount == 1)
                SetDisable('#ButtonDeletePage', true);

            $('#PageCount').val(pageCount);
            $('#pageCountField').text(pageCount);

            var currentPage = parseInt($('#PageIndex').val());
            if (currentPage >= pageCount) {
                currentPage = currentPage - 1;
                $('#PageIndex').val(currentPage);
                $('#pageIndexField').text(currentPage + 1);
            }

            if (currentPage == 0)
                SetDisable('#PreviousPageButton', true);

            if (currentPage + 1 >= pageCount - 1)
                SetDisable('#NextPageButton', true);

            UpdatePreview(currentPage);
        }
        function PreviousPage() {
            SetDisable('#NextPageButton', false);

            var prevPageNum = parseInt($('#PageIndex').val()) - 1;
            $('#PageIndex').val(prevPageNum);
            $('#pageIndexField').text(prevPageNum + 1);

            if (prevPageNum == 0)
                SetDisable('#PreviousPageButton', true);

            UpdatePreview(prevPageNum);
        }
        function NextPage() {
            SetDisable('#PreviousPageButton', false);

            var nextPageNum = parseInt($('#PageIndex').val()) + 1;
            $('#PageIndex').val(nextPageNum);
            $('#pageIndexField').text(nextPageNum + 1);

            var pageCount = parseInt($('#PageCount').val())
            if (nextPageNum >= pageCount - 1)
                SetDisable('#NextPageButton', true);

            UpdatePreview(nextPageNum);
        }
    </script>
}
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;

namespace AspNetCoreDemos.OfficeFileAPI {
    public partial class SplitMergeController : OfficeDemoController {
        IMergeDemoService service;

        public SplitMergeController(ILogger<SplitMergeController> logger, IWebHostEnvironment hostingEnvironment, IMergeDemoService service)
            : base(logger, hostingEnvironment) {
            this.service = service;
        }
    }
}
using System;
using System.Collections.Generic;
using System.IO;
using DevExpress.Pdf;

namespace AspNetCoreDemos.OfficeFileAPI {
    public class PdfModelBase : IDisposable {
        readonly PdfDocumentProcessor processor;
        MemoryStream stream;
        List<PdfPageModel> items = new List<PdfPageModel>();

        public MemoryStream Stream { get { return stream; } }
        protected PdfDocumentProcessor Processor { get { return processor; } }
        protected PdfDocument Document { get { return processor.Document; } }
        public List<PdfPageModel> Items { get { return items; } }

        public string DocumentUrl { get; set; }
        public int PageIndex { get; set; }
        internal virtual string SessionKey { get; }
        public PdfPreviewModel PreviewModel { get; internal set; }

        public PdfModelBase() {
            processor = new PdfDocumentProcessor();
            PreviewModel = new PdfPreviewModel();
        }

        protected void CreateEmptyDocument() {
            stream = new MemoryStream();
            Processor.CreateEmptyDocument(stream);
            Document.Creator = "PDF Document Processor Demo";
            Document.Producer = "Developer Express Inc., " + AssemblyInfo.Version;
            Document.Author = "DevExpress Inc.";
        }

        public virtual void LoadDocument(byte[] data) {
            using(MemoryStream stream = new MemoryStream(data))
                LoadDocument(stream);
        }

        protected void LoadDocument(Stream stream) {
            processor.LoadDocument(stream, true);
            for(int pageNumber = 1; pageNumber <= processor.Document.Pages.Count; pageNumber++)
                Items.Add(new PdfPageModel(processor, pageNumber));
        }

        public void Dispose() {
            if(processor != null)
                processor.Dispose();
            GC.SuppressFinalize(this);
        }
    }
}
using System.IO;

namespace AspNetCoreDemos.OfficeFileAPI {
    public class PdfPageDeletionModel : PdfModelBase {

        public PdfPageDeletionModel() {
            PreviewModel.PreviewDocumentAction = "DocumentViewPartial";
            PreviewModel.ControllerName = "SplitMerge";
            PageCount = 8;
            PreviewModel.IsViewWithoutSidePanel = true;
        }

        public int PageCount { get; set; }
        internal override string SessionKey { get { return "DeletePageFileKey"; } }

        public byte[] DeletePage(int pageNumber) {
            if(Processor.Document.Pages.Count > 0)
                Processor.DeletePage(pageNumber);
            using(MemoryStream stream = new MemoryStream()) {
                Processor.SaveDocument(stream);
                stream.Position = 0;
                Items.Clear();
                LoadDocument(stream);
                return stream.GetBuffer();
            }
        }
    }
}
using Microsoft.AspNetCore.Mvc;

namespace AspNetCoreDemos.OfficeFileAPI {
    public partial class SplitMergeController {
        const string pageDeleteSessionKey = "DeletePageFileKey";
        const string pageDeleteDefaultFile = "/Documents/Pdf/PageDeletion.pdf";

        public IActionResult PdfPageDeletion() {
            return GetDemoView<PdfPageDeletionModel>("PdfPageDeletion", "DeletePageFileKey", HostingEnvironment.ContentRootPath + pageDeleteDefaultFile);
        }

        public IActionResult DocumentViewPartial(PdfPageDeletionModel pageDeletionModel) {
            return base.DocumentViewPartial(pageDeletionModel);
        }

        public IActionResult PdfDeleteCurrentPage(int pageNumber) {
            using(PdfPageDeletionModel model = new PdfPageDeletionModel()) {
                byte[] data;
                if(HttpContext.Session.TryGetValue(pageDeleteSessionKey, out data)) {
                    model.LoadDocument(data);
                    HttpContext.Session.Set(pageDeleteSessionKey, model.DeletePage(pageNumber + 1));
                    return new EmptyResult();
                } else {
                    return new BadRequestResult();
                }
            }
        }
    }
}