.epub ファイルを取得して解凍し、ファイルを編集してcontent.opt
カスタム メタデータを追加し、コンテンツを圧縮して新しい .epub ファイルを作成するプログラムを作成しています。私は電子書籍リーダーと .epub エディターの両方に caliber を使用しています。これは、.epub ファイルのコンテンツだけでなく、.epub のメタデータも非常に簡単に編集できるためです。
新しい .epub ファイルを正常に作成できました。この新しいファイルは、キャリバーと Kobo 電子リーダーの両方で読み取れることをテストしました。
ただし、元の .epub ファイルのメタデータは新しい .epub ファイルに転送されません。さらに、口径で .epub ファイルを編集できません。試してみると、「epub に META-INF/container.xml がありません」というエラーが表示されます。複数の .epub ファイルを使用してみましたが、同じ結果とエラーが発生します。
解凍した元の .epub ファイルの内容は次のとおりです。
META/INF
↳container.xml
content.opf
mimetype
pages_styles.css
[title]_split_000.xhtml
[title]_split_001.xhtml
.....
[title]_split_012.xhtml
[title]_split_013.xhtml
stylesheet.css
toc.ncx
新しく作成された .epub ファイルの解凍されたディレクトリは、元のディレクトリと同じです。実行diff -r -q /[title]_original /[title]_recreated
しても出力は生成されません。これは、それらが実際に同一であることを示します。そのため、口径がどのようにしてあるファイルを読み取って別のファイルを読み取れないのかわかりません。このエラーは、caliber が META-INF/container.xml ファイルを見つけられないことを示しているようです。このファイルは、メタデータがディレクトリ内のどこに保存されているかを電子書籍リーダーに伝えるために使用されます。
注: 何が起こっているのかを把握できるようになるまで、解凍または圧縮プロセス中に元の .epub のコンテンツを編集していません。
go run main.go zip.go
2 つの go ファイルと .epub ファイル [タイトル] を含むディレクトリでコマンドを実行しています。
main.go
package main
import (
// "log"
// "strings"
)
type FileLocations struct {
src string
ext string
dest string
}
func main() {
fileName := "[title]"
temp := FileLocations{
src: fileName,
ext: ".epub",
dest: fileName,
}
// Unzip the zip/epub file
UnzipHelper(temp.src, temp.ext, temp.dest)
// Zip the modified directory
ZipHelper(temp.src, temp.ext)
}
func UnzipHelper(src string, ext string, dest string) error {
_, err := Unzip(src, ext, dest)
if err != nil {
return err
}
return nil
}
func ZipHelper(src string, ext string) error {
err := Zip(src, ext)
if err != nil {
return err
}
return nil
}
ジップ・ゴー
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func Unzip(src string, ext string, dest string) ([]string, error) {
file := src + ext
var filenames []string
r, err := zip.OpenReader(file)
if err != nil {
return filenames, err
}
defer r.Close()
for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
// Check for ZipSlip
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
return filenames, fmt.Errorf("%s: illegal file path", fpath)
}
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}
rc, err := f.Open()
if err != nil {
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()
if err != nil {
return filenames, err
}
}
// Remove zip file so it can be recreated later
os.Remove(file)
return filenames, nil
}
func Zip(filename string, ext string) error {
// Creates .epub file
file, err := os.Create(filename + ext)
if err != nil {
log.Fatal("os.Create(filename) error: ", err)
}
defer file.Close()
w := zip.NewWriter(file)
defer w.Close()
walker := func(path string, info os.FileInfo, err error) error {
fmt.Println("Crawling: " + path)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
f, err := w.Create(path)
if err != nil {
return err
}
_, err = io.Copy(f, file)
if err != nil {
return err
}
return nil
}
err = filepath.Walk(filename, walker)
if err != nil {
log.Fatal("filepath.Walk error: ", err)
}
return err
}