Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using java.util.zip to construct valid epub

Tags:

java

zip

epub

I built a method that recursively adds the contents of a folder to a zip document with the file extension "epub," which is basically what an epub is except for one thing:

the first document in the archive must be named "mimetype," the type must be specified application/epub+zip, and must start with a byte offset of 38. Is there a way to add the mimetype to the archive with offset 38?

The method I built nearly works. It constructs an epub which can be read by most e-readers, but it doesn't validate. EpubCheck gives this error:

mimetype contains wrong type (application/epub+zip expected)

This is an issue that does not exist in the original test epub, but shows up in the reconstructed epub. And I double checked that the contents of the unzipped/rezipped mimetype file are correct.

The method is too much to post here. But this is what I'm using to add the mimetype file to the archive:

out = new ZipOutputStream(new FileOutputStream(outFilename));

FileInputStream in = new FileInputStream(mimeTypePath);
out.putNextEntry(new ZipEntry("mimetype"));

int len;
while ((len = in.read(buf)) > 0) {
   out.write(buf, 0, len);
}

out.closeEntry();
in.close();
out.close();
like image 709
objectivesea Avatar asked Aug 15 '11 08:08

objectivesea


1 Answers

According to Wikipedia's description of the Open Container Format, the mimetype file should be the first entry in the ZIP file, and it should be uncompressed.

Based on your sample code alone, it's not clear whether you're specifying that the mimetype file should be STORED (uncompressed).

The following seems to get me past the "mimetype contains wrong type" error:

private void writeMimeType(ZipOutputStream zip) throws IOException {
    byte[] content = "application/epub+zip".getBytes("UTF-8");
    ZipEntry entry = new ZipEntry("mimetype");
    entry.setMethod(ZipEntry.STORED);
    entry.setSize(20);
    entry.setCompressedSize(20);
    entry.setCrc(0x2CAB616F); // pre-computed
    zip.putNextEntry(entry);
    zip.write(content);
    zip.closeEntry();
}

Confirmed: removing the setMethod(), setSize(), setCompressedSize() and setCrc() lines yields the "mimetype contains wrong type" error from epubcheck.

like image 65
Alistair A. Israel Avatar answered Nov 12 '22 14:11

Alistair A. Israel