【发布时间】:2021-12-12 01:29:57
【问题描述】:
我已经开始使用这个包来创建一个.epub 文件,我必须说它比我之前尝试过的javascript库(epub-zipper)要流畅得多
但是,有一个小细节我无法解决:EPUB 3.2 规范states 那
OCF ZIP 容器中的第一个文件必须是 mimetype 文件
而且它不能被压缩。我已经达到了“未压缩”的条件,但我不知道如何满足“zip 存档中的第一个文件”的条件。这是我的代码:
main :: IO ()
main = do
mimetype <- mkEntrySelector "mimetype"
createArchive "conmocion.epub" $ do
packDirRecur Deflate (\s -> mkEntrySelector $ "META-INF/" ++ s) "./ePub/META-INF"
packDirRecur Deflate (\s -> mkEntrySelector $ "es/" ++ s) "./ePub/es"
loadEntry Store mimetype "./ePub/mimetype"
我在epub online validator 中收到以下错误
Mimetype file entry is missing or is not the first file in the archive.
知道如何将 mimetype 文件作为存档中的第一个文件吗?
编辑
代码现在是:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Codec.Archive.Zip
import qualified Data.Map as M
main :: IO ()
main = do
mimetype <- mkEntrySelector "000mimetype"
createArchive "conmocion.epub" $ contents mimetype
createArchive "conmocion.zip" $ contents mimetype
where
contents x = do
loadEntry Store x "./ePub/mimetype"
packDirRecur Deflate (mkEntrySelector . ("META-INF/" ++)) "./ePub/META-INF"
packDirRecur Deflate (mkEntrySelector . ("es/" ++) ) "./ePub/es"
packDirRecur Deflate (mkEntrySelector . ("assets/" ++) ) "./ePub/assets"
test :: IO ()
test = do
entries <- withArchive "conmocion.epub" (M.keys <$> getEntries)
mapM_ print entries
当我调用test 函数时,它会打印以下内容:
ghci> test
"000mimetype"
"assets\\all.css"
"es\\chapters\\c1.xhtml"
"es\\chapters\\c2.xhtml"
"es\\chapters\\c3.xhtml"
"es\\chapters\\c4.xhtml"
"es\\chapters\\c5.xhtml"
"es\\chapters\\c6.xhtml"
"es\\chapters\\c7.xhtml"
"es\\chapters\\c8.xhtml"
"es\\chapters\\c9.xhtml"
"es\\docs\\colophon.xhtml"
"es\\docs\\coverback.xhtml"
"es\\docs\\coverfront.xhtml"
"es\\docs\\epigraph.xhtml"
"es\\docs\\legal.xhtml"
"es\\docs\\nav.xhtml"
"es\\docs\\notice.xhtml"
"es\\docs\\thanks.xhtml"
"es\\es.opf"
"META-INF\\container.xml"
当我提取 zip 文件时,可以在里面找到 000mimetype 文件,其中只有 application/epub+zip 行
编辑 2
引用EPUB Open Container Format (OCF) 3.2
4.3 OCF ZIP Container Media Type Identification
The first file in the OCF ZIP Container MUST be the mimetype file, which meets the following requirements:
The contents of the mimetype file MUST be the MIME media type [RFC2046] string application/epub+zip encoded in US-ASCII [US-ASCII].
The mimetype file MUST NOT contain any leading or trailing padding or white space.
The mimetype file MUST NOT begin with the Unicode byte order mark U+FEFF.
The mimetype file MUST NOT be compressed or encrypted, and there MUST NOT be an extra field in its ZIP header.
【问题讨论】:
-
将
loadEntry放在第一个packDirRecur之前会发生什么? -
epub 验证器返回相同的错误
-
当您将文件解压缩到一个单独的位置时,mimetype 文件的内容是您所期望的吗?列出edoc文件的内容时,mimetype文件是不是第一个?
-
mimetype 文件里面只有一行,
application/epub+zip,当我使用 Haskell 包中的withArchive函数列出 epub 文件的内容时,它总是按字母顺序打印文件,无论我是在 do 块的开头还是结尾调用 loadEntry -
在这一点上,我怀疑软件包本身在添加文件时正在重新排序文件,尽管粗略查看源代码似乎不太可能。您将不得不想出一个解决方法或使用不同的库。