0

.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.go2 つの 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
}
4

2 に答える 2