EPUB Tools本機處理

EPUB 使用指南

EPUB 容器內部結構——從 mimetype 到 spine 的完整鏈路

一個 EPUB 檔案可以視為一層層的引用鏈:閱讀器從 ZIP 容器開始,讀取 mimetype 確認檔案類型,然後找到 container.xml 取得 Package Document 的路徑,再透過 content.opf 的 manifest 與 spine 來決定閱讀順序。

第一層:mimetype

mimetype 是 EPUB 容器的最外層標示。它是一個沒有副檔名的純文字檔案,位於 ZIP 的根目錄,且必須是 ZIP 中的第一個 entry。內容只有一行:application/epub+zip,不包含任何換行字元或 BOM。這個設計讓閱讀器可以在讀取 ZIP 的 Central Directory 之前,直接從第一個 local file header 讀取檔案內容,快速判斷檔案是否為 EPUB。如果 mimetype 被壓縮(Deflate)或不在第一個位置,閱讀器必須完整掃描整個 ZIP 才能確認檔案類型,這在某些嵌入式裝置上會造成效能問題。

第二層:META-INF/container.xml

container.xml 是 EPUB 的「目錄索引」。這個 XML 檔案位於 META-INF/container.xml,其內容指定了 EPUB 的 Package Document 位置。一個典型的 container.xml 長這樣:

<?xml version="1.0"?><container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"><rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles></container>

這個 XML 的關鍵屬性是 full-path,它是一個相對於 EPUB root 的路徑,指向實際的 Package Document。EPUB 可以有多個 rootfile 元素,但通常只有一個。如果 EPUB 包含多個 rendition(例如同時包含文字版與有聲書版),container.xml 會包含多個 rootfile 來分別指向不同的 Package Document。

第三層:content.opf(Package Document)

content.opf 是 EPUB 的核心描述檔案,它使用 XML 格式定義了書籍的所有 metadata、資源清單與閱讀順序。OPF 檔案包含三個主要區段。第一個是 metadata,包含書名、作者、出版者、語言、ISBN 等 Dublin Core 資訊。第二個是 manifest,列出 EPUB 中所有檔案的 ID、路徑與媒體類型,每一個檔案——包括 XHTML、CSS、圖片、字型——都必須在 manifest 中有一個對應的 item 元素。第三個是 spine,定義了閱讀順序,spine 中的 itemref 元素依序引用 manifest 中的 ID,決定閱讀器翻頁時的順序。

spine 的順序不一定等於檔案在 ZIP 中的實體順序。例如,一本 EPUB 的 ZIP 中可能包含 cover.xhtmlchapter1.xhtmlchapter2.xhtml,但 spine 的順序可能是 chapter1chapter2cover(如果封面被放在最後)。閱讀器會按照 spine 的順序來顯示內容,而不是按照 ZIP 的 entry 順序。

第四層:內容檔案

content.opf 的 manifest 中列出的所有檔案就是 EPUB 的實際內容。這些檔案通常包括 XHTML 文件(書籍正文)、CSS 樣式表、圖片(JPEG、PNG、SVG)、字型檔案(WOFF、WOFF2)以及可能的音訊或影片檔案。這些檔案可以放在任何目錄結構中,只要 manifest 中的 href 路徑正確即可。值得注意的是,EPUB 3 支援包含 JavaScript 的互動式內容,但 EPUB 2 的規格中不允許執行 JavaScript。

容器結構的驗證流程

EPUB Tools 在驗證一個 EPUB 的容器結構時,會按照以下的順序進行檢查。第一步:確認 ZIP 可以正常讀取,且 mimetype 存在於第一個 entry。第二步:讀取 mimetype 的內容,確認它是否為 application/epub+zip。第三步:在 ZIP 的根目錄尋找 META-INF/container.xml,並解析其 XML 內容。第四步:從 container.xml 取得 full-path 屬性,並確認該路徑指向的檔案存在於 ZIP 中。第五步:解析 content.opf,檢查 manifest 中的所有檔案是否都存在於 ZIP 中,以及 spine 中的 itemref 是否都對應到 manifest 中的項目。

如果任何一個步驟失敗,EPUB 的容器結構就不完整。但不同的閱讀器對這個結構的嚴格程度不同:有些閱讀器即使 container.xml 中的路徑稍微錯誤,仍然可以透過猜測找到 content.opf;有些閱讀器則會嚴格按照標準,只要任何一個環節不符合就拒絕匯入。這也解釋了為什麼同一本 EPUB 可能在 A 閱讀器上正常顯示,在 B 閱讀器上卻顯示格式錯誤。

相關指南:EPUB 無法匯入怎麼辦 · EPUB 其實就是 ZIP · EPUB 變成資料夾怎麼辦 · 閱讀器匯入疑難排解

manifest 中的每個 item 元素都包含三個必要屬性:id(唯一識別碼,供 spine 的 itemref 引用)、href(相對於 OPF 檔案位置的檔案路徑)以及 media-type(檔案的 MIME 類型,例如 application/xhtml+xmltext/cssimage/jpeg)。如果 manifest 中的 media-type 與檔案的實際內容不符,某些閱讀器可能無法正確渲染該檔案。例如,將 image/png 誤標記為 image/jpeg 可能導致圖片無法顯示。此外,manifest 中遺漏任何一個實際存在的檔案,並不會造成閱讀器錯誤,但該檔案將無法被 spine 引用,等同於不存在於 EPUB 中。

spine 的 itemref 元素除了 idref 屬性之外,還可以包含 linear 屬性(值為 yesno),用來指示該頁面是否屬於主要閱讀線性流程。設定為 linear="no" 的頁面(如封面、版權頁、目錄)不會被計入閱讀進度,閱讀器在「跳至下一章」時也會跳過這些頁面。EPUB 3 的 spine 還支援 page-progression-direction 屬性,可以在 OPF 的 spine 元素上設定 ltrrtl 來控制書籍的閱讀方向,這對中文直排書籍的顯示尤其重要,因為直排書籍需要設定為 rtl 才能正確從右至左翻頁。

開始檢查 EPUB