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 PdfDocumentBuilder
class. You start by creating an instance of
the class with Create
method. To generate a PDF, you call Generate
method of the class.
Generate
can save the output to a file or a stream. Either version of the method requires a
delegate of 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,681 passed Total NuGet downloads 4,234,061
Encryption
To encrypt the output PDF, call Encryption
method before Generate
method.
You would need to create and provide an encryption handler. To encrypt PDF with passwords, use a
handler of 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 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 Info
method before 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 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 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 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 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 Dispose
for every stream it gets through the stream provider. You
must dispose of the stream provider instance yourselves.