Skip to main content
Skip table of contents

Streaming publication from a HTTP server

Introduction

The Colibrio reading system framework is designed to be "lazy" when working with publications.

Resources are loaded and processed only when needed. This means that for the majority of cases, only a small portion ("chunks") of the EPUB or PDF file is required at a time while reading.

This guide explains how to create a reading system that is capable of "streaming" EPUB and PDF files from a remote HTTP server by using HTTP range request.

This allows your users to immediately start reading EPUBs or PDFs without downloading the complete file.

Pre-requisites

The server hosting the publication must support range requests:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

If the server hosting the publications is on another domain, you also need to make sure that CORS has been configured correctly so the browser allows your webapp to perform cross-domain requests:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Implementing IRandomAccessDataSource

To be able to "stream" publication to the reading system, you need to implement the interface IRandomAccessDataSource from colibrio-core-io-base.d.ts.

The following example code shows how a IRandomAccessDataSource implementation could look that uses HTTP range requests:

TYPESCRIPT
import { IRandomAccessDataSource } from './colibrio-core-io-base';
import { HttpRequest } from './HttpRequest';

export class HttpDataSource implements IRandomAccessDataSource {

    constructor(private url: string, private size: number) {
    }

    /**
     * Fetch a chunk of data from the data source between a start and end offset.
     * This method must not throw an exception in case of a non-recoverable error.
     *
     * @param startOffset - An index into the data source indicating the first byte to include in the result buffer
     * @param endOffset - An index into the data source indicating the first byte that will *not* be included in the result buffer. 
     *                    Must be larger than 'start', and less than or equal to the value returned by getSize().
     * @return Resolved with an ArrayBuffer containing the requested data. Rejected if it is not possible to fetch the requested data.
     */
    fetchChunk(startOffset: number, endOffset: number): Promise<ArrayBuffer> {
        // Our endOffset is  *exclusive*, while range request includes the byte with the end offset. 
        return HttpRequest.sendRangeRequest(this.url, startOffset, endOffset - 1);
    }

    /**
     * Get the size of the data in bytes.
     */
    getSize(): number {
        return this.size;
    }

}


export class HttpRequest {

    static sendRangeRequest(url: string, start: number, end: number): Promise<ArrayBuffer> {
        return new Promise<ArrayBuffer>((resolve, reject) => {
            let request = HttpRequest.createRequest('GET', url, reject);

            request.setRequestHeader("Range", `bytes=${start}-${end}`);
            request.onload = function(_event) {
                resolve(this.response);
            };
            request.send();
        });
    }


    private static createRequest(verb: 'GET' | 'HEAD', url: string, rejectFn: (arg?: any) => void): XMLHttpRequest {

        let request = new XMLHttpRequest();
        request.open(verb, url , true);
        request.responseType = "arraybuffer";

        request.onerror = function(_event) {
            rejectFn(this.status + ': ' + this.statusText);
        };

        request.onabort = function(_event) {
            rejectFn(this.status + ': ' + this.statusText);
        };

        request.ontimeout = function(_event) {
            rejectFn('TIMEOUT');
        };

        return request;
    }
}

Loading the publication using IRandomAccessDataSource

Using the HttpDataSource above, the Colibrio Reader Framework can now stream EPUB publications over HTTP:

TYPESCRIPT

import {OcfResourceProvider} from './colibrio-core-publication-epub';


let remoteEpub = new HttpDataSource('https://my-domain-with-publications/someEpub.epub', 43134054);
let ocfResourceProvider = await EpubOcfResourceProvider.createFromRandomAccessDataSource(remoteEpub);

let publication = ocfResourceProvider.getDefaultPublication();
// ... and then continue setup the reading system as usual.

The colibrio framework can stream PDF publications over HTTP with:

TYPESCRIPT
import {PdfPublication} from './colibrio-core-publication-pdf';

let remotePdf = new HttpDataSource('https://my-domain-with-publications/somePdf.pdf', 38284889);
let publication = PdfPublication.createFromRandomAccessDataSource(remotePdf);
// ... and then continue setup the reading system as usual.
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.