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:

Embedded document layers

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:

Embedded document layers

The static method CreateNewDocument of the SmartDocument class creates a blank document using a ServerTextControl TX Text Control .NET Server for ASP.NET
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;
}
view raw test.cs hosted with ❤ by GitHub

It opens the TX Text Control document editor that can be used to create a document:

Embedded document layers

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;
}
view raw test.cs hosted with ❤ by GitHub

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);
}
}
view raw test.cs hosted with ❤ by GitHub

Back in the overview, this new document can be edited or viewed:

Embedded document layers

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:

Embedded document layers

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);
}
}
view raw test.cs hosted with ❤ by GitHub

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!