I have a source HTML document generated from an ASPX.
I then convert the html to PDF using ABCPDF.
The html has a signature area, which is just a text box with a border.
I need a signature field inside the PDF with a name that I can pass on.
The PDF will be sent to a third-party who will correspond with the client and then digitally sign the PDF and send it back.
Given that I have an html document, or PDF, how do I programmatically add the blank PDF signature field around the original html signature area or somehow relate the two?
Here is a sample application to demonstrate some of the things I'm doing:
namespace ABCPDFHtmlSignatureTest
{
using System.Diagnostics;
using System.IO;
using System.Reflection;
using WebSupergoo.ABCpdf8;
using WebSupergoo.ABCpdf8.Objects;
/// <summary>
/// The program.
/// </summary>
public class Program
{
/// <summary>
/// The file name.
/// </summary>
private const string FileName = @"c:\temp\pdftest.pdf";
/// <summary>
/// The application entry point.
/// </summary>
/// <param name="args">
/// The args.
/// </param>
public static void Main(string[] args)
{
var html = GetHtml();
var pdf = GetPdf(html);
/* save the PDF to disk */
File.WriteAllBytes(FileName, pdf);
/* open the PDF */
Process.Start(FileName);
}
/// <summary>
/// The get PDF.
/// </summary>
/// <param name="html">
/// The html.
/// </param>
/// <returns>
/// The <see cref="byte"/>.
/// </returns>
public static byte[] GetPdf(string html)
{
var document = new Doc();
/* Yes, generate PDF fields for the html form inputs */
document.HtmlOptions.AddForms = true;
document.AddImageHtml(html);
/* We can determine the location of the field */
var signatureRect = document.Form["Signature"].Rect;
MakeFieldsReadOnly(document.Form.Fields);
return document.GetData();
}
/// <summary>
/// The get html.
/// </summary>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public static string GetHtml()
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ABCPDFHtmlSignatureTest.HTMLPage1.html"))
{
using (var streamReader = new StreamReader(stream))
{
return streamReader.ReadToEnd();
}
}
}
/// <summary>
/// The make fields read only.
/// </summary>
/// <param name="fields">
/// The fields.
/// </param>
private static void MakeFieldsReadOnly(Fields fields)
{
foreach (var field in fields)
{
if (field.Name == "Signature") continue;
field.Stamp();
}
}
}
}
Hopefully this can help someone else.
I ended up using both ABCPDF and iTextSharp.
I used ABCPDF to convert the HTML to PDF, and to tell me where the element is, and then I used iTextSharp to put the blank signature field over it.
There were a couple of "gotchas" in this project:
Here is a sample project to demonstrate the solution.
The sample html: (notice the abcpdf-tag-visible: true part in the style of the signature field, this will help us to see where the element is placed in the PDF)
Here is a screen shot of the PDF with a blank signature field, opened with Adobe afterwards.
A sample console application to help test out the PDF converters:
When running inside the web server and still generating the HTML, you can use this class to change the relative (virtual) paths to physical (UNC) paths:
You can use the class like this: