Digital signature WebViewer

694 views
Skip to first unread message

Amit Rajput

unread,
Mar 24, 2015, 12:14:52 PM3/24/15
to pdfnet-w...@googlegroups.com
Hi Team,

We are in evaluation process and found PDFTron WebViewer and SDK a great feature to support our product.

We are using Asp.Net Web forms

What we accomplished, view the pdf in WebViewer, add a custom image annotation, to "Sign Here".
Now as WebViewer don't support to add digital sign fields, we are using custom annotation to tell user where they need to sign nad then we'll place digital signature at this location.

Challenges:
1. Save annotation using Asp.Net
2. Read annotation and add digital signature field exactly at the custom annotation place
3. Remove custom annotation
4. Place digital signature (You have already provided an example to place digital sign using pfx)

Or any better approach is also welcome.

Thanks in advance

Matt Parizeau

unread,
Mar 24, 2015, 2:16:50 PM3/24/15
to pdfnet-w...@googlegroups.com
Hi Amit,

If I understand correctly you have already successfully added a custom annotation where you want the digital signature to be. You just want to be able to send that location to your server that you can apply it to the PDF?

So your annotation already has X/Y coordinates and a page number. That information is in XOD coordinates, so you'll have to convert those values to PDF coordinates. You can do that using the GetPDFCoordinates function. For example:
var doc = readerControl.docViewer.GetDocument();
var pdfLocation = doc.GetPDFCoordinates(myAnnot.PageNumber - 1, myAnnot.X, myAnnot.Y);
// pdfLocation.x and pdfLocation.y are the coordinates of the annotation on the PDF

Now that you have the coordinates you can send them to your server. By default when WebViewer saves annotation data it sends a POST request with the data to a URL on your server. You could do something similar where you have a URL on your server that is expecting the signature data and from your JavaScript code you make an AJAX call to that URL with the x and y location. For an example of this you can look at ReaderControl.js, find the saveAnnotations function and look for the $.ajax call.

If you then want to remove the custom annotation from WebViewer you can use code like the following:
var annotManager = readerControl.docViewer.GetAnnotationManager();
annotManager
.DeleteAnnotation(myAnnot);

Let me know if you need any clarifications.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Amit Rajput

unread,
Mar 25, 2015, 1:44:37 PM3/25/15
to pdfnet-w...@googlegroups.com
Hi Matt,

Thanks for the reply

I am able to create Custom annotation but I am not finding a way to save the annotation using Asp.Net

<html style="height:100%;">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <script src="../../jquery-1.7.2.min.js" type="text/javascript"></script>
    <script src="../../lib/WebViewer.min.js" type="text/javascript"></script>
    <script type="text/javascript">

    $(function() {
        var viewerElement = document.getElementById('viewer');
        var myWebViewer = new PDFTron.WebViewer({
            type: "html5",
            path: "../../lib",
            initialDoc: "../files/form1.xod",
            serverUrl: "default.aspx",
            documentId: "213",
            config: "diamond.js",
            enableAnnotations: true,
            streaming: false
        }, viewerElement);
    });
    </script>
</head>

<body style="width:100%;height:100%;margin:0px;padding:0px;overflow:hidden">
    <div id="viewer" style="height: 100%; overflow: hidden;"></div>
</body>


>>you can look at ReaderControl.js, find the saveAnnotations function and look for the $.ajax call

I am not able to find saveAnnotations function in ReaderControl.js
Can you please tell me how can I save the annotation using aspx or ashx (generic handler)
ReaderControl.js

Amit Rajput

unread,
Mar 25, 2015, 1:44:37 PM3/25/15
to pdfnet-w...@googlegroups.com
Hi Matt,

Thanks for the reply.

I am able create custom annotation in WebViewer, now able to drag/ drop custom annotation in WebViewer.

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <script src="../../jquery-1.7.2.min.js" type="text/javascript"></script>
    <script src="../../lib/WebViewer.min.js" type="text/javascript"></script>
    <script type="text/javascript">

    $(function() {
        var viewerElement = document.getElementById('viewer');
        var myWebViewer = new PDFTron.WebViewer({
            type: "html5",
            path: "../../lib",
            initialDoc: "../files/form1.xod",
            serverUrl: "default.aspx",   //Is it required to be an .php only? Can we use .aspx/ .ashx
            documentId: "form1",
            config: "diamond.js",
            enableAnnotations: true,
            streaming: false
        }, viewerElement);
    });
    </script>
</head>

<body style="width:100%;height:100%;margin:0px;padding:0px;overflow:hidden">
    <div id="viewer" style="height: 100%; overflow: hidden;"></div>
</body>
</html>

But I am not able to save the annotation. Can we save/ load annotation in Asp.Net?

Matt Parizeau

unread,
Mar 25, 2015, 4:08:02 PM3/25/15
to pdfnet-w...@googlegroups.com
Hi Amit,

Here are a few clarifications. By default how WebViewer saves and loads annotations is by sending POST and GET requests to the URL specified by the serverUrl option. This URL is just an endpoint on your server so it can be php, aspx or anything you like as long as your server will handle the POST and GET requests. You can refer to annotationHandler.php for an example of how it could be done.

However from what you described it sounds like you don't actually want to save the custom annotations but instead you only want to send information about their location to the server so that the server can add a digital signature to the original PDF. If that's all you want to do then it would be possible to do something simpler like I described in my previous post. I suggested looking at saveAnnotations so you could see how it calls $.ajax with the URL and data. You could do this yourself to just send the x and y coordinates.

You can find the saveAnnotations function on line 1102 of the file you attached and the relevant call to $.ajax at line 1147.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Amit Rajput

unread,
Mar 26, 2015, 2:12:05 PM3/26/15
to pdfnet-w...@googlegroups.com
Hi Matt,

Thanks for the help.

Now I am able to save the annotation to XOD :)

My approach is to save annotation to xod and later share the document to other user, so they can view the annotation only.

I am able to drag an image as stamp annotation, but later when I view this, it comes as text "stamp". So I changed the stamp text of stamp in translation-en.json, "stamp": "Sign"
And changed Draft:"Draft" to Draft:"Sign" in CoreControl.js
Now it gives me a Stamp annotation "Sign" on the document. But I really wanted to put the original image which I put as a annotation.

Further is it possible to hide annotation panel but display the annotation toolbar. I mean, don't allow user to put any annotation but the user should be able to view all the annotation placed on the document in left panel.

Thanks

diamond.js

Matt Parizeau

unread,
Mar 26, 2015, 7:15:54 PM3/26/15
to pdfnet-w...@googlegroups.com
Hi Amit,

There's actually a currently undocumented feature to create a stamp from an image. Here's some sample code:

var annotManager = readerControl.docViewer.GetAnnotationManager();

var stampAnnot = new Annotations.StampAnnotation();
stampAnnot
.PageNumber = 1;
stampAnnot
.X = 100;
stampAnnot
.Y = 250;
stampAnnot
.Width = 275;
stampAnnot
.Height = 40;
stampAnnot
.Author = annotManager.GetCurrentUser();
stampAnnot
.ImageData = 'data:image/png;base64,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';

annotManager
.AddAnnotation(stampAnnot);
annotManager
.DrawAnnotations(stampAnnot.PageNumber);


For this feature to work you'll have to use the latest unofficial build http://www.pdftron.com/ID-zJWLuhTffd3c/WebViewer/WebViewer_1.8.1.30154.zip

To allow viewing of annotations but disallow adding any more you can switch WebViewer to read only mode. To do this pass the option enableReadOnlyMode: true to the PDFTron.WebViewer constructor.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Amit Rajput

unread,
Mar 27, 2015, 1:26:53 PM3/27/15
to pdfnet-w...@googlegroups.com
Hi Matt,

My Current status is, able to get/ save annotation to xfdf. Able to export the annotation to the pdf.


                        FDFDoc fdf_doc2 = new FDFDoc(FDFDoc.CreateFromXFDF(X_Fdf_File));
                        fdf_doc2.Save(HttpContext.Current.Server.MapPath("~/Demo/custom-annotations/Fdf/form1_annots.xfdf"));

                        using (PDFDoc doc = new PDFDoc(HttpContext.Current.Server.MapPath("~/doc/WebViewer_Developer_Guide.pdf")))
                        {
                            doc.FDFMerge(fdf_doc2);
                            doc.Save(HttpContext.Current.Server.MapPath("~/Demo/custom-annotations/Pdf/form1_filled_with_annots.pdf"), SDFDoc.SaveOptions.e_linearized);
}

This creates a new pdf file with the annotation. But I want to replace the annotation with digital signature fields. Please check attachment for xfdf file.

Thanks
4545.xfdf

Matt Parizeau

unread,
Mar 27, 2015, 1:48:45 PM3/27/15
to pdfnet-w...@googlegroups.com
Hi Amit,

You can refer to our digital signature sample for PDFNet: https://www.pdftron.com/pdfnet/samplecode/DigitalSignaturesTest.cs.html

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Amit Rajput

unread,
Mar 30, 2015, 12:59:17 PM3/30/15
to pdfnet-w...@googlegroups.com
Hi Matt,

If I place two digital signature widget it works ok.
 but with following code not all stamps are replace by Digital signature widget. Can you tell me what I am missing?

 using (PDFDoc doc = new PDFDoc(Server.MapPath("~/doc/WebViewer_Developer_Guide.pdf")))
                        {
                            doc.FDFMerge(fdf_doc2);

 PageIterator itr = doc.GetPageIterator();
                            for (; itr.HasNext(); itr.Next())
                            {
                                   Page page = itr.Current();
                                int num_annots = page.GetNumAnnots();

                                for (int i = 0; i < num_annots; ++i)
                                {
                                    Annot annot = page.GetAnnot(i);
                                    if (annot.IsValid() == false) continue;
 
                                    switch (annot.GetType())
                                    {
                                        case Annot.Type.e_Stamp:
                                            Field sig = doc.FieldCreate(signId, Field.Type.e_signature);
                                            pdftron.PDF.Annots.Widget a = pdftron.PDF.Annots.Widget.Create(doc,
                                            new Rect(bbox.x1, bbox.y1, bbox.x2, bbox.y2), sig); a.SetAppearance
                                            (CreateSignatureAppearance(doc));
                                            page.AnnotPushBack(a);
                                            num_annots++;
                                            page.AnnotRemove(annot);
                                            break;
default:
                                            break;
}
                                 }
                            }
doc.Save(Server.MapPath("~/Demo/custom-annotations/Pdf/form1_filled_with_annots.pdf"), SDFDoc.SaveOptions.e_linearized);
                       }

Amit Rajput

unread,
Mar 30, 2015, 12:59:17 PM3/30/15
to pdfnet-w...@googlegroups.com
What I've tried so far,
using (PDFDoc doc = new PDFDoc(Server.MapPath("~/form1_filled_with_annots.pdf")))
                        {
                            doc.InitSecurityHandler();

                            Field sig = doc.FieldCreate("sig", Field.Type.e_signature);
                            pdftron.PDF.Annots.Widget a = pdftron.PDF.Annots.Widget.Create(doc,
                            new Rect(50, 100, 100, 200), sig); a.SetAppearance
                            (CreateSignatureAppearance(doc));

doc.Save(HttpContext.Current.Server.MapPath("~/Pdf/form1_filled_with_annots.pdf"), SDFDoc.SaveOptions.e_linearized);
                        }  

  static Obj CreateSignatureAppearance(PDFDoc doc)
        {
            ElementBuilder b = new ElementBuilder();
            ElementWriter w = new ElementWriter();
            w.Begin(doc);

            pdftron.PDF.Image img = pdftron.PDF.Image.Create(doc, Server.MapPath("~/sign.gif"));
            int width = img.GetImageWidth();
            int height = img.GetImageHeight();
            Element img_element = b.CreateImage(img, 0, 0, width, height);
            w.WritePlacedElement(img_element);

            Obj stm = w.End();

            // Set the bounding box
            stm.PutRect("BBox", 0, 0, width, height);
            stm.PutName("Subtype", "Form");

            w.Dispose();
            b.Dispose();

            return stm;
        }

but no signature field is added on the form. Am I missing something here?
Can I replace all the stamp annotation to signature field with respective position maintained.

Amit Rajput

unread,
Mar 30, 2015, 12:59:17 PM3/30/15
to pdfnet-w...@googlegroups.com
Hi Matt,

Is there anything wrong with the code?


Amit Rajput

unread,
Mar 30, 2015, 12:59:17 PM3/30/15
to pdfnet-w...@googlegroups.com
Hi Matt,

Now I am able to add the digital signature field. Feels good to get this working.
It is just that I need to find the coordinate from xfdf, is there a way to load the stamp annotation from xfdf as signature. Or I need to loop xfdf and find stamp annotation one by one and mark them as signature.

Thanks

Amit Rajput

unread,
Mar 30, 2015, 12:59:17 PM3/30/15
to pdfnet-w...@googlegroups.com
Hi Matt,

I have already looked into the sample.

// Obtain the signature form field from the PDFDoc via Annotation;
Field sigField = doc.GetField("Signature1");

But I have "Stamps" on pdf,  so how to replace a "Stamp" with digital sign field and sign there.
Or at the time creation
of fdf file fromxfdf, we can replace the annotation?




Matt Parizeau

unread,
Mar 30, 2015, 3:57:07 PM3/30/15
to pdfnet-w...@googlegroups.com
Hi Amit,

I think the problem with the code might be how you're looping over the annotations. You're adding the widget to the end of the list and removing the current annot so you're going to miss some annotations because the indexes are going to change.

I think you should be able to just remove the stamp annotation you're looking at and then insert at that same index. You also shouldn't have to increment num_annots because you've added one annotation and removed another, so a net change of zero.

page.AnnotRemove(annot);
page
.AnnotInsert(i, a);

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Amit Rajput

unread,
Apr 8, 2015, 12:24:47 PM4/8/15
to pdfnet-w...@googlegroups.com
Thanks Matt,

It works perfectly. 
Reply all
Reply to author
Forward
0 new messages