Some test text!

PDF Manipulation

In this document
chevron_rightOverview
chevron_rightRotating pages
chevron_rightCropping pages
chevron_rightRemoving pages
chevron_rightMoving Pages
chevron_rightInserting Pages
chevron_rightExtracting pages from PDF
chevron_rightSaving the updated PDF
chevron_rightRelated Links

linkOverview

When WebViewer is running in client only mode it is able to perform many different kinds of page manipulations. These include rotating, cropping, reordering, adding, and deleting pages. Instead of temporarily modifying the document in the viewer, these operations modify the actual PDF data.

This means that when the download button is pressed or getFileData is called, the returned PDF will have the manipulations applied and they will be visible in any PDF viewer.

Currently if you're using the WebViewer Server deployment option then PDF manipulation is not supported.

linkRotating pages

Pages in PDF documents may have a "built-in" rotation which is the rotation that the page will be initially displayed at in a viewer. When inside WebViewer a temporary page rotation can also be applied.

Using the WebViewer API it's possible to rotate pages both in the viewer and in the document data. Pages rotated by the user through the rotate buttons in the UI will only apply a temporary rotation.

Rotation values can be found in the CoreControls.PageRotation enum, their name and values are:

EnumValue
e_00
e_901
e_1802
e_2703

UI rotation functions can be found on the DocumentViewer object. These rotation functions modify what is being displayed in WebViewer, not the actual PDF data.

  • getRotation: Returns the rotation of a page in the UI
  • getCompleteRotation: Returns the total rotation of a page, this is the temporary page rotation plus any permanently built in document rotation
  • setRotation: Sets the rotation for the specified page or all pages in WebViewer
  • rotateClockwise: Rotates the specified page or all pages clockwise in WebViewer
  • rotateCounterClockwise: Rotates the specified page or all pages counterclockwise in WebViewer

There is only one function for manipulating rotation in the actual PDF data and it's found on the Document object.

  • rotatePages: Rotate an array of pages, this does affect the PDF data and the downloaded file. It returns a promise when the operation is complete.

An example of rotations being used can be seen below

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var rotation = viewerElement.querySelector('iframe').contentWindow.CoreControls.PageRotation;
var page1 = 1, page2 = 2, page3 = 3;

// ---- Rotating pages in WebViewer ----------------
docViewer.rotateClockwise(page1);
docViewer.getRotation(page1); // returns 1 i.e. PageRotation.e_90
docViewer.getCompleteRotation(page1); // returns 1 i.e. PageRotation.e_90

// At this point, page 1 is rotated in WebViewer while page 2 and 3 are not rotated.
// However if the user downloads the PDF, all pages are NOT rotated.
// This is because the pages are rotated in the UI but the file data hasn't been changed.

// ---- Rotating pages in the PDF file data ---------------
doc.rotatePages([page1], rotation.e_90).then(function(pagesArray) {
  // At this point the first page is rotated 180 degrees relative to
  // its orientation originally but if the file is downloaded page 1
  // will only be rotated 90 degrees. This is because it has a 90 degree
  // temporary rotation and a 90 degree built in document rotation

  docViewer.getRotation(page1);
  // 1 i.e. PageRotation.e_90

  docViewer.getCompleteRotation(page1);
  // 2 i.e. PageRotation.e_180, getCompleteRotation returns the total rotation of the page
  // 90 degrees temporary rotation + 90 degrees permanent rotation

  // permanently rotate 180 degrees more
  return doc.rotatePages([page1], rotation.e_180);
}).then(function(pagesArray) {
  docViewer.getRotation(page1);
  // still return 1 i.e. PageRotation.e_90, the temporary rotation hasn't changed

  docViewer.getCompleteRotation(page1);
  // now returns 0 i.e. PageRotation.e_0, 90 degrees temporary rotation + 270 degrees permanent rotation
});

linkCropping pages

PDF pages can be cropped using the cropPages function. Simply pass in an array of pages to crop and the amount to be cropped from each side. One thing to note is that sides are based on the document rotation instead of the UI or total rotation.

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var rotation = viewerElement.querySelector('iframe').contentWindow.CoreControls.PageRotation;
var cropTop = 100, cropLeft = 0, cropRight = 0, cropBottom = 0;
var page1 = 1, page2 = 2, page3 = 3;

doc.getPageInfo(page1 - 1); // {width: 612, height: 792}

doc.cropPages([page1], cropTop, cropBottom, cropLeft, cropRight)
.then(function(pagesArray) {
  doc.getPageInfo(page1); // {width: 612, height: 692}
  return doc.rotatePages([page1], rotation.e_90);
}).then(function(pagesArray) {
  docViewer.rotateCounterClockwise(page1);
  // rotate the first page back so that it appears upright in the viewer
  doc.getPageInfo(page1 - 1); // {width: 692, height: 612}, width and height get swapped
  return doc.cropPages([page1], cropTop, cropBottom, cropLeft, cropRight);
}).then(function(pagesArray) {
  doc.getPageInfo(page1 - 1); // {width: 692, height: 512}
  // Even though the page appears upright, the document is rotated 90 degree clockwise
  // So the left side of the document is cropped
});

linkRemoving pages

Pages can be removed from the PDF document using the removePages function.

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var page1 = 1, page2 = 2, page3 = 3;

docViewer.getPageCount(); // 3

doc.removePages([page2]).then(function(pagesArray) {
  // at this point page 2 has been removed from the document
  docViewer.getPageCount(); //2
});

linkMoving Pages

Pages in the PDF document can be reordered using the movePages function.

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var page1 = 1, page2 = 2, page3 = 3;

var pagesToMove = [page2, page3];
var insertBefore = page1;

doc.movePages(pagesToMove, insertBefore).then(function(pagesArray) {
  // pages are now in the order of [page2, page3, page1];
});

linkInserting Pages

Pages can be inserted into the current PDF document using the insertBlankPages and insertPages functions. Inserting blank pages is fairly straight forward.

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();

var width = 612;
var height = 792;
docViewer.getPageCount(); // 3

// Insert blank pages
doc.insertBlankPages([2, 3], width, height).then(function(pagesArray) {
  // The document now contains [page1, newBlankPage1, page2, newBlankPage2, page3]
  docViewer.getPageCount(); // 5
};

More likely someone will want to insert pages from one PDF into another. To achieve this, instantiate a new Document object and load data into it using the loadAsync function. In the example below, the loadAsync function takes in an ExternalPdfPartRetriever object to load a PDF from an external URL but any PartRetriever can be used to load data.

Currently there aren't any functions to duplicate pages in the current document. If someone wanted to copy a page, instantiate a new Document object and load the current PDF data into it using a PartRetriever and insert the page into the current document.
var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var documentID = 'another.pdf';
// documentID can be anything but should be unique
var documentType = 'pdf';

var licenseKey = 'Enter licenseKey here';
var workerHandlers = {};

var docToInsert = new CoreControls.Document(documentID, documentType);
CoreControls.getDefaultBackendType()
.then(function(backendType) {
  var workerTransportPromise = CoreControls.initPDFWorkerTransports(backendType, workerHandlers, licenseKey);
  var options = { workerTransportPromise: workerTransportPromise };

  // any 'partRetrievers' can be used here
  var partRetriever = new CoreControls.PartRetrievers.ExternalPdfPartRetriever(
    'http://localhost/pdf/another.pdf'
  );

  docToInsert.loadAsync(partRetriever, function(err) {
    var pagesToInsert = [4, 5, 6];
    var pageIndexToInsert = doc.getPageCount() + 1;
    // in this example doc.getPageCount() returns 3

    doc.insertPages(docToInsert, pagesToInsert, pageIndexToInsert)
    .then(function() {
      // page 4, 5, and 6 from 'another.pdf' has been inserted into to the current pdf
      doc.getPageCount(); // 6
    });
  }, options);
});

linkExtracting pages from PDF

If the user only wants to download part of a document, the extractPages function can be used to download specific pages. For example:

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
var pagesToExtract = [2, 3];

var annotManager = docViewer.getAnnotationManager();
// only include annotations on the pages to extract
var annotList = annotManager.getAnnotationsList().filter(function(annot) {
  return pagesToExtract.indexOf(annot.PageNumber) > -1;
});
var xfdfString = annotManager.exportAnnotations({ annotList: annotList });

doc.extractPages(pagesToExtract, xfdfString).then(function(data) {
  var extension = 'pdf';

  var arr = new Uint8Array(data);
  var blob = new Blob([arr], { type: 'application/pdf' });

  // in this example we are using FileSaver.js library but any technique to save a blob works
  saveAs(blob, 'downloaded.pdf');
});

linkSaving the updated PDF

Once you've applied changes to the document data you'll probably want to do something with the updated PDF like letting the user download it or sending it back to your server.

If you just want to let the user download the edited file then no extra changes are necessary as pressing the download button will save the modified PDF to the user's computer.

If you want to do get the modified PDF as an ArrayBuffer then you can use the getFileData function on Document. For example:

var docViewer = myWebViewer.getInstance().docViewer;
var doc = docViewer.getDocument();
// include annotations with the document
var options = {
  xfdfString: docViewer.getAnnotationManager().exportAnnotations()
};

doc.getFileData(options).then(function(data) {
  var arr = new Uint8Array(data);
  var blob = new Blob([arr], { type: 'application/pdf' });
  // upload blob to your server
});

linkRelated Links

Web sample and code can be found below