Data Providers

In addition to loading documents directly using StorageFile, IBuffer, or a Uri, PSPDFKit for Windows includes support for creating DocumentSources from data providers. A data provider defines a common interface for PSPDFKit to read and write PDF documents from custom sources. This is especially helpful if you want to support your own encryption or compression scheme.

Existing Data Providers

PSPDFKit for Windows ships with two predefined providers:

You can also write your own custom data providers by implementing the IDataProvider interface. The Catalog project contains another two examples of custom providers:

These providers can be used to create a DocumentSource, which is then used by the Controller to display the document:

Copy
1
2
3
4
5
6
_fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);

var dataProvider = new ExampleDataProvider(_fileStream);
var documentSource = DocumentSource.CreateFromDataProvider(dataProvider);

await PDFView.Controller.ShowDocumentAsync(documentSource);

Custom Data Provider

Creating your own custom data provider is a straightforward process. You’ll have to create a class that implements the IDataProvider interface and all its methods. These methods should help you structure your data in a way that’s compatible with PSPDFKit for Windows.

Reading

For reading, the ReadAsync method is used internally when needed. The content of this method will vary depending on how the documents are obtained in your own application. Within the ReadAsync method is where your chosen data structures should be adapted to match the IBuffer return expected by PSPDFKit for Windows, like so:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
private readonly IRandomAccessStream _data;

private async Task<IBuffer> ReadAsync(uint size, uint offset)
{
    if (offset >= _data.Size)
    {
        throw new Exception("Attempt to read beyond the end of a random access stream.");
    }

    var copy = new Buffer(size);
    _data.Seek(offset);
    return await _data.ReadAsync(copy, size, InputStreamOptions.ReadAhead);
}

Note that your method must ensure the size and offset used for the reading operation are valid according to your data.

Writing

Writing is done separately using data sinks. These are classes specifically for writing data. They represent a destination to write to and allow you to export documents directly to streams or other desired mediums.

PSPDFKit for Windows ships with two default data sinks, which support DataWriters and IRandomAccessStreams. Similar to data providers, you can also implement your own data sinks through IDataSink.

The WriteDataAsync method allows you to control this process:

Copy
1
2
3
4
5
6
7
8
9
10
11
public IRandomAccessStream Stream { get; set; }

private async Task<bool> WriteDataAsync(IBuffer data)
{
    using (var outputStream = Stream.GetOutputStreamAt(Stream.Size))
    {
        await outputStream.WriteAsync(data);
    }

    return true;
}

Depending on the medium being used and your settings, the DataSinkOption class tells your data sink whether to start at the beginning of the stream or to append to it. For example, when incremental saves or annotation flattening are enabled, IDataSink must be empty, as the entire document is written out and appending is not supported.

Finally, documents can be exported to your IDataSink with the Document.ExportToDataSinkAsync method:

1
await PDFView.Document.ExportToDataSinkAsync(new ExampleDataSink(option) { Stream = _fileStream }, exportOptions);

Our Catalog application includes two examples of IDataSink implementations.