All formats

goreader/epub

LanguageGo
LicenseMIT
Repositorygithub.com/taylorskalyo/goreader (package epub)
Documentationpkg.go.dev/github.com/taylorskalyo/goreader/epub
Depends onGo standard library only (archive/zip, encoding/xml)
Read / writeyes / no

The epub package of goreader (a terminal EPUB reader) parses an EPUB in a few small structs: the container’s rootfiles, the OPF metadata (title, creator, language, identifier, publisher, description, dates), the manifest items and the spine. Each manifest item can be opened as an io.ReadCloser to read its XHTML or image data. It also reads chapter labels from the EPUB 3 navigation document or the EPUB 2 NCX.

It’s intentionally small: metadata fields are single strings (only the first dc:creator is kept), and it doesn’t convert XHTML to text. Use it when you need to list or extract the contents of an EPUB without pulling in a large dependency.

Installation#

Shell
go get github.com/taylorskalyo/goreader/epub

Basic usage: read metadata and chapters#

Go
package main

import (
	"fmt"
	"io"
	"log"

	"github.com/taylorskalyo/goreader/epub"
)

func main() {
	rc, err := epub.OpenReader("book.epub")
	if err != nil {
		log.Fatal(err)
	}
	defer rc.Close()

	// the package (content.opf); books almost always have exactly one
	book := rc.Rootfiles[0]
	fmt.Println("Title:   ", book.Title)
	fmt.Println("Author:  ", book.Creator)
	fmt.Println("Language:", book.Language)

	// chapters in reading order
	for _, itemref := range book.Spine.Itemrefs {
		r, err := itemref.Open()
		if err != nil {
			log.Fatal(err)
		}
		data, err := io.ReadAll(r)
		r.Close()
		if err != nil {
			log.Fatal(err)
		}
		label := book.ItemName(itemref.HREF) // title from the table of contents, if any
		fmt.Printf("%s (%s): %d bytes\n", itemref.HREF, label, len(data))
	}
}

How to list all files in an EPUB manifest#

Go
for _, item := range rc.Rootfiles[0].Manifest.Items {
	fmt.Printf("%-20s %-30s %s\n", item.ID, item.HREF, item.MediaType)
}

How to extract images from an EPUB#

Go
for i := range book.Manifest.Items {
	item := &book.Manifest.Items[i]
	if !strings.HasPrefix(item.MediaType, "image/") {
		continue
	}
	r, err := item.Open()
	if err != nil {
		log.Fatal(err)
	}
	out, err := os.Create(path.Base(item.HREF))
	if err != nil {
		log.Fatal(err)
	}
	io.Copy(out, r)
	out.Close()
	r.Close()
}

(imports: io, os, path, strings)

How to read an EPUB from memory#

NewReader takes an io.ReaderAt and size, e.g. a file you downloaded into a byte slice:

Go
data, err := os.ReadFile("book.epub")
if err != nil {
	log.Fatal(err)
}
r, err := epub.NewReader(bytes.NewReader(data), int64(len(data)))
if err != nil {
	log.Fatal(err)
}
fmt.Println(r.Rootfiles[0].Title)

Tips#