futurepress / epub.js

Enhanced eBooks in the browser.
http://futurepress.org
Other
6.47k stars 1.11k forks source link

Passing ArrayBuffer to EPub constructer unexpected behavior #916

Open Vinpasso opened 5 years ago

Vinpasso commented 5 years ago

Consider the following code:

function setupEBook(ebook) {
    let reader = new FileReader();
    reader.onload = displayEBook.bind(null, reader);
    reader.readAsArrayBuffer(ebook);
}

function displayEBook(reader) {
    let book = ePub(reader.result);
    let rendered = book.renderTo("book-panel", {method: "default", width: "100%", height: "100%"});
    let displayPromise = rendered.display();
    displayPromise.then(function () {
        console.log("Displayed");
    }, function (reason) {
        console.log("Fail: " + reason);
    });
    console.log(displayPromise);
}

epub.js just seems to kind of sit there and do nothing, the promises are never fulfilled. Now if I change the following line let book = ePub(reader.result); to let book = ePub(); book.open(reader.result); the book loads correctly. This is also the method the example uses, but the documentation says the constructor should be able to accept the ArrayBuffer.

The following code snippet from book.js is suspicious to me:

        // Allow passing just options to the Book
        if (typeof(options) === "undefined" &&
              typeof(url) !== "string" &&
            url instanceof Blob === false) {
            options = url;
            url = undefined;
}

I think it unsets the URL even though it should not. There might need to be an additional check here?

By the way, thanks to the maintainers for their effort on this project.

wnabil commented 5 years ago

This is a working implementation "in typescript" that I'm currently use for arraybuffer, simply convert it to a blob then load the book


     // create blob
      const blob: any = new Blob([arrayBuffer], { type: 'application/epub+zip' });
      // load the epub from arrayBuffer
      this.instance = new Book(blob);
      // wait until the book loaded
      this.instance.ready.then(() => {
        // create continuous scrolled options
    const options: RenditionOptions = {
      manager: 'continuous',
      flow: 'scrolled',
    };
    // render to the div id "reader"
    this.instance.renderTo(selector, options);
    // display the content
    this.instance.rendition.display();
      });
mbret commented 4 years ago

Thanks a lot @wnabil, you made me realize the library can handle zip by itself, I was struggling the whole day trying to download my blob and unziping it etc. Was not able to make it work and there you are, giving the one line that just works 🤷

I don't get why this library does not have a more detailed documentation at this point.