PDF/A-3 permits the embedding of files in any format. PDF/A-3 documents allow the progression from electronic paper to an electronic container that holds the human and machine-readable versions of a document. Applications can extract the machine-readable portion of the PDF document in order to process it. A PDF/A-3 document can contain an unlimited number of embedded documents for different processes.
Smart Document Container
In this sample application, we use a PDF document as a container to store an editable version and the DocumentViewer annotations as embedded files. The following illustration shows this container setup:
The advantage in this scenario is that the PDF can be send to anyone outside of your infrastructure and the current version of the document is always visible for everyone using a simple Acrobat Reader. The viewable version always reflects the most current version.
Sample Concept
In this sample, you can create a new Smart Document by clicking New Smart Document:
The static method CreateNewDocument of the SmartDocument class creates a blank document using a Server
╰ TXTextControl Namespace
╰ ServerTextControl Class
The ServerTextControl class implements a component that provide high-level text processing features for server-based applications. instance. This document is saved in the internal Text Control format to be embedded into a newly created PDF document.
public static string CreateNewDocument() { | |
var DocumentName = Guid.NewGuid().ToString() + ".pdf"; | |
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) { | |
tx.Create(); | |
byte[] dataTx; | |
// save the blank document in the internal TX format | |
tx.Save(out dataTx, TXTextControl.BinaryStreamType.InternalUnicodeFormat); | |
// create an attachment | |
EmbeddedFile embeddedFile = new EmbeddedFile("original.tx", dataTx, null); | |
embeddedFile.Relationship = "Source"; | |
TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings() { | |
EmbeddedFiles = new EmbeddedFile[] { embeddedFile } | |
}; | |
// save a PDF with the attached Text Control document embedded | |
tx.Save("App_Data/" + DocumentName, | |
TXTextControl.StreamType.AdobePDF, | |
saveSettings); | |
} | |
return DocumentName; | |
} |
It opens the TX Text Control document editor that can be used to create a document:
When loading the original, embedded document, the ExtractSmartDocument method opens the PDF in order to check the embedded files for the original document or the annotations JSON. In case the document should be edited, the embedded original document is loaded into the editor.
public static SmartDocument ExtractSmartDocument(string DocumentName) { | |
SmartDocument smartDocument = new SmartDocument(); | |
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) { | |
tx.Create(); | |
// the load PDF document | |
TXTextControl.LoadSettings loadSettings = new LoadSettings(); | |
tx.Load("App_Data/" + DocumentName, | |
TXTextControl.StreamType.AdobePDF, | |
loadSettings); | |
// loop through all attachments to find the original document | |
// and the annotations | |
foreach (EmbeddedFile file in loadSettings.EmbeddedFiles) { | |
if (file.FileName == "original.tx") | |
smartDocument.Document = Convert.ToBase64String((byte[])file.Data); | |
if (file.FileName == "annotations.json") | |
smartDocument.Annotations = System.Text.Encoding.UTF8.GetString((byte[])file.Data); | |
} | |
smartDocument.Name = DocumentName; | |
} | |
return smartDocument; | |
} |
When saving the original document, the method SaveDocument is loading the modified version into a ServerTextControl to create the updated PDF representation container by including itself as an embedded file.
public static void SaveDocument(SmartDocument smartDocument) { | |
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) { | |
tx.Create(); | |
// load the edited document | |
tx.Load(Convert.FromBase64String(smartDocument.Document), | |
TXTextControl.BinaryStreamType.InternalUnicodeFormat); | |
// create an attachment from the edited document | |
EmbeddedFile embeddedFile = new EmbeddedFile("original.tx", | |
Convert.FromBase64String(smartDocument.Document), | |
null); | |
embeddedFile.Relationship = "Source"; | |
// attache the files | |
TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings() { | |
EmbeddedFiles = new EmbeddedFile[] { embeddedFile } | |
}; | |
// save the document as PDF with the edited original attachment | |
tx.Save("App_Data/" + smartDocument.Name, | |
TXTextControl.StreamType.AdobePDF, | |
saveSettings); | |
} | |
} |
Back in the overview, this new document can be edited or viewed:
When clicking View (Annotations), the original, editable version of the document is opened in the TX Text Control DocumentViewer that can be used to add annotations:
When clicking Save Annotations, the annotations JSON is stored as an embedded file in the container PDF. Therefore, the associated container PDF is loaded and the original document is extracted. This original document is then loaded and used to create the new PDF document to embed the original version and the annotation JSON.
public static void SaveAnnotations(SmartDocument smartDocument) { | |
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) { | |
tx.Create(); | |
// load the SmartDocument PDF | |
TXTextControl.LoadSettings loadSettings = new LoadSettings(); | |
tx.Load("App_Data/" + smartDocument.Name, | |
TXTextControl.StreamType.AdobePDF, | |
loadSettings); | |
// find the original embedded document | |
foreach (EmbeddedFile file in loadSettings.EmbeddedFiles) { | |
if (file.FileName == "original.tx") | |
smartDocument.Document = Convert.ToBase64String((byte[])file.Data); | |
} | |
// load the original document | |
tx.Load(Convert.FromBase64String(smartDocument.Document), | |
BinaryStreamType.InternalUnicodeFormat); | |
// create an attachment for the original document | |
EmbeddedFile efOriginal = new EmbeddedFile("original.tx", | |
Convert.FromBase64String(smartDocument.Document), | |
null); | |
efOriginal.Relationship = "Source"; | |
// create an attachment for the annotations | |
EmbeddedFile efAnnotations = new EmbeddedFile("annotations.json", | |
Encoding.UTF8.GetBytes(smartDocument.Annotations), | |
null); | |
efAnnotations.Relationship = "Source"; | |
// attach the files | |
TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings() { | |
EmbeddedFiles = new EmbeddedFile[] { efOriginal, efAnnotations } | |
}; | |
// save the SmartDocument as PDF with attachments | |
tx.Save("App_Data/" + smartDocument.Name, | |
TXTextControl.StreamType.AdobePDF, | |
saveSettings); | |
} | |
} |
Download the Sample
This concept is very flexible and can be used for your own formats and workflows. To test this on your own, download the fully-functional sample project from GitHub and let us know, if you have any questions or feedback.
Happy coding!