I am writing a program that takes an .epub file, unzips it, edits the content.opt
file to add custom metadata, then zip the contents to create a new .epub file. I am using calibre as both my e-reader and my .epub editor, since calibre makes it very easy to edit both the metadata for an .epub as well as the contents of an .epub file.
I am able to successfully create a new .epub file. I have tested this new file can be read both with calibre and my Kobo e-reader.
However, none of the metadata from the original .epub file transfers over to the new .epub file. Additionally I am unable to edit the .epub file in calibre. When I try I get the error "No META-INF/container.xml in epub". I have tried using multiple .epub files and I get the same results and errors.
Unzipped, the contents of the original .epub file is as follows:
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
The unzipped directory for the newly created .epub file is identical to the original. Running diff -r -q /[title]_original /[title]_recreated
produces no output, which would indicate they are in fact identical. So I am unsure how calibre can read one file and not read another. The error seems to indicate that calibre is somehow unable to find the META-INF/container.xml file, which is used to tell an e-reader where metadata is being stored in the directory.
Note: I am not editing any content for the original .epub during the unzipping or zipping process until I am able to figure out what is happening.
EDIT: Including the code I used below. I am running the command go run main.go zip.go
in the directory with the two go files and the .epub file [title]:
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 }
zip.go
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 }
https://stackoverflow.com/questions/65799618/why-wont-calibre-read-the-metadata-on-a-recreated-epub-file January 20, 2021 at 05:13AM
没有评论:
发表评论