The Crystal Programming Language Forum

Writing a file to Zip as STORED not DEFLATE

I am playing around with writing ePubs and need to have the first file (the mimetype) added as-is, that is without using Deflate compression (called STORED). I can see from the notes in the code I need to set entry.compression_method, crc32, compressed and uncompressed file size, but can not figure out how to do that. I am new to Crystal and any help would be much appreciate.

Hi RedDevil, welcome to the forums!

I found how to do it in the specs:

I wrote the zip library a long time ago so I can’t remember why it’s needed to specify the crc32, compressed and uncompressed size. I also tried to open the resulting zip in Mac’s Finder and it doesn’t work, but it works if I read it using Zip::Reader so there might be a bug there.

If that works for you then great! Otherwise please open an issue. Thank you!

Many thanks. I also had problems with reading the zip on linux. On using ‘unzip -t zipfile’ the result indicated an error of an extra 20 bytes and a bad zipfile offset. When comparing with the same zip produced with my earlier code the source became clear. In the End of Central Directory Record the offset field is 20 bytes low. Changing this with hexedit fixed the problem and the zip opens correctly with just the ‘mimetype’ file. I will look into this further as I add more files. Do you want me to open an issue on this?

Just off to bed and had a thought. The 20 bytes is the size of the mimetype file in my example. If I change the content of this file the offset error follows with the new file size so this should be easy to find the error. I will check the code tomorrow.

Thanks for the research! I sent a fix here: https://github.com/crystal-lang/crystal/pull/8142

2 Likes

Thanks. Not sure if it is relevant but I changed from using IO::Memory to:
File.open("./file.zip", “w”) do |file|
Zip::Writer.open(file) do |zip|