Golang重新压缩EPUB时如何确保mimetype为Zip首个文件
解决Go中EPUB重新压缩时mimetype验证失败的问题
EPUB规范强制要求mimetype文件满足三个核心条件:
- 是压缩包中的第一个文件
- 采用无压缩存储(Store方式)
- 文件内容严格为
application/epub+zip(无多余空格、换行)
你遇到的PKG-006报错,本质就是这三个条件未同时满足,以下是纯Go的修复方案:
核心修复代码
import ( "archive/zip" "io" "os" ) func RepackEPUB(inputPath, outputPath string) error { // 打开源EPUB文件 srcFile, err := os.Open(inputPath) if err != nil { return err } defer srcFile.Close() // 创建目标EPUB文件 dstFile, err := os.Create(outputPath) if err != nil { return err } defer dstFile.Close() zipW := zip.NewWriter(dstFile) defer zipW.Close() // 第一步:写入mimetype(必须是第一个文件,无压缩) mimeHeader := &zip.FileHeader{ Name: "mimetype", Method: zip.Store, // 禁用压缩,符合EPUB规范 } mimeWriter, err := zipW.CreateHeader(mimeHeader) if err != nil { return err } if _, err = mimeWriter.Write([]byte("application/epub+zip")); err != nil { return err } // 读取源EPUB中的其他文件,按顺序写入(跳过原mimetype) srcZip, err := zip.OpenReader(inputPath) if err != nil { return err } defer srcZip.Close() for _, file := range srcZip.File { if file.Name == "mimetype" { continue // 跳过源文件中的mimetype,避免重复写入 } // 创建文件头,保留原文件的元数据和压缩方式 fileHeader := &zip.FileHeader{ Name: file.Name, Method: file.Method, // 可改为zip.Deflate强制统一压缩方式 } fileHeader.SetModTime(file.ModTime()) fileWriter, err := zipW.CreateHeader(fileHeader) if err != nil { return err } srcFile, err := file.Open() if err != nil { return err } defer srcFile.Close() if _, err = io.Copy(fileWriter, srcFile); err != nil { return err } } return nil }
关键注意事项
- 写入顺序绝对优先:
mimetype必须是第一个被写入到zip包的文件,不能有任何文件(包括META-INF/container.xml)在它之前 - 压缩方式必须为Store:如果用
zip.Deflate压缩mimetype,epubcheck会直接报错 - 内容严格匹配:
mimetype的内容不能有任何多余字符,必须是application/epub+zip
你之前尝试的直接写入字节、优先复制container.xml等方法,都没解决核心的顺序和压缩方式问题,按上述代码实现后,再用epubcheck验证即可通过。
内容的提问来源于stack exchange,提问作者Peter Kaufman
相关产品推荐
相关产品推荐

