Building documents
Of course, you need to generate a PDF document with your data. But often enough, you also want to encrypt the PDF file with passwords. And you usually want to add PDF metadata to the output file.
Keep reading to know how to instruct the generator to encrypt PDF files. How to specify document author and keywords.
This article is part of a series about Layout API for PDF generation. If you are new to the API, read the Getting Started with Layout API part first.
Create & Generate
The entry point of Layout API is the
PdfDocumentBuilder class. You start by
creating an instance of the class with the Create
method. To generate a PDF, you call the
Generate method of the class.
The Generate
can save the output to a file or a stream. Either version of the method requires a
delegate of the Action
<Document> type as the second
parameter. In the delegate, you describe the document you want to get. The library will generate a
PDF based on the description.
14,820 passed Total NuGet downloads 4,998,853
Encryption
To encrypt the output PDF, call the Encryption method before the Generate method.
You would need to create and provide an encryption handler. To encrypt PDF with passwords, use a handler of the PdfStandardEncryptionHandler type.
PdfDocumentBuilder.Create()
.Encryption(new PdfStandardEncryptionHandler("owner", "user"))
.Generate("encrypted-with-password.pdf", doc => doc.Pages(_ => { }));
You can also encrypt PDF with certificates. Check the Encrypt PDF documents article. It contains detailed information about encryption handlers and PDF permissions.
PDF Metadata
In some workflows, it is very important to specify proper PDF keywords and PDF author in the output PDF. Layout API provides an easy way for this. Call the Info method before the Generate method and provide the metadata values in the delegate.
PdfDocumentBuilder.Create()
.Info(info =>
{
info.Author = $"{Environment.UserName}";
info.Title = "Generate encrypted PDF with custom metadata";
info.Keywords = "Metadata keywords encryption";
})
.Generate("metadata.pdf", doc => doc.Pages(_ => { }));
Options
For the same content, the library can create PDF files with different internal structure. These options will affect the output PDF.
Version
Use the Version method to set the minimum PDF format version for the output PDF.
PdfDocumentBuilder.Create()
.Version(PdfVersion.Pdf17)
.Generate("version.pdf", doc => doc.Pages(_ => { }));
Please note that the library can create a PDF with a larger version than specified. It happens when the document contents requires a newer version. To put it differently: when the document uses features not available in the specified version of the PDF standard.
Object streams
By default, the library uses objects streams in generated PDFs. This helps to produce smaller, better compressed files.
You can instruct the API to create PDF files without object streams using the ObjectStreams method.
PdfDocumentBuilder.Create()
.ObjectStreams(false)
.Generate("no-object-streams.pdf", doc => doc.Pages(_ => { }));
I suggest you keep using object streams unless there are some regulatory requirements. Or when some other parts of your workflow can not process documents with object streams.
Stream provider
The library uses streams as the intermediate storage. When generating a PDF, it does so for images and other large objects. The library gets streams through the stream provider. There is always one associated with the current PdfDocumentBuilder instance.
The library uses the PdfMixedStorageStreamProvider by default. This stream provider implementation provides streams that keep data in memory. These streams flush their contents to temporary files when there is too much data. This allows to reduce memory consumption and avoid LOH fragmentation.
You can use your own implementation of the IPdfStreamProvider interface when generating PDF files. One reason for the change might be a slow and/or expensive disk operations. Cloud environments might fit into this description.
This code shows how to generate PDF completely in memory, without temporary files. Please note that this will require a lot more memory than with the default options.
using (var memoryOnlyProvider = new PdfMemoryStreamProvider())
{
PdfDocumentBuilder.Create()
.StreamProvider(memoryOnlyProvider)
.Generate("created-without-temp-files.pdf", doc => doc.Pages(_ => { }));
}
The library eventually calls the Dispose
for every stream it gets through the stream provider.
You must dispose of the stream provider instance yourselves.