Split the requirement into three parts, each has an off-the-shelf piece:
- Show only one page of the uploaded PDF - render the page with pdf.js in a custom coach view (managed asset pdf.min.js); pdfDoc.getPage(pdfDoc.numPages) gives the last page, getPage(1) the first. Word files: convert to PDF on the server first (LibreOffice headless, or the ECM rendition service).
- Let the user choose the signature position - draw the page on a <canvas>, capture a click / drag on it and store the coordinates relative to the page size (x, y, page, width); show a preview rectangle.
- Stamp the signature - on the server with PDFBox: open the document, take the page, draw the signature image (PNG from the user's signature pad or the stored signature) at the coordinates, save a new version and attach it to the instance.
// browser (custom coach view): read the click position on the rendered page
canvas.onclick = function (e) {
var r = canvas.getBoundingClientRect(), scale = viewport.scale;
me.context.binding.set("value", { page: pageNumber, x: (e.clientX - r.left) / scale, y: (canvas.height - (e.clientY - r.top)) / scale }); // PDF origin = bottom left
};// server (PDFBox in a Java Integration): stamp the signature PNG
PDDocument doc = PDDocument.load(pdfBytes); PDPage page = doc.getPage(pageIndex);
PDImageXObject img = PDImageXObject.createFromByteArray(doc, pngBytes, "sig");
PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);
cs.drawImage(img, x, y, 150, 50); cs.close();
ByteArrayOutputStream out = new ByteArrayOutputStream(); doc.save(out); doc.close();
If the signature must be a digital signature (certificate based, not a picture), use PDFBox's PDSignature with a keystore, or hand the document to an external signing service (DocuSign, Adobe Sign) through its REST API and receive the signed file back through a UCA - BPM then only orchestrates.
References