Edited on February 17, 2013: I was alerted by a reader that this code is broken now. To fix the bug I needed to make one code tweak (noted below) and update to the latest copy of zip.js.
Following up on my Sunday blog post on comics, I thought it would be fun to share a little experiment I built this weekend. Comic books are available in a compressed format typically called CBRs or CBZs. These aren't a special format, just simple compressed archives. CBRs are RAR files and CBZs are zips. While there doesn't appear to be good support for RAR files (I've only found a Java library to list the contents), the Zip format is much more widely used and easy to work with. In fact, you can find an excellent JavaScript implementation: zip.js I thought it might be fun to try using that to build my own web-based CBZ reader. Here's how I did it.
First, I added drag/drop support to my application so that users could simply drag in their local CBZ files. Instead of a div, I made the entire page a target for drop events:
Edit on February 17, 2013: Chrome recently changed something (or changed after I blogged) that now makes you listen for, and prevent, the dragover event. This is a very minor update:
The dropHandler needs to do a few things. First - it needs to figure out the type of drop. Don't forget that people can drag/drop blocks of text from other applications. What I want is to listen for files. Even better - I need to ensure that one file is dropped, not multiple. Here's the snippet for that logic.
Ok, now for the fun part. My application needs to try to decompress the zip file to the file system. In order to do that I am making use of the HTML5 File API. Earlier on I did a quick request for some temporary file storage - which is pretty simple:
Having the file system means I can extract the images out of the zip into the directory and refer to them later. We have access to the file from the drop event, so it is a simple matter of:
- Pass the file data to zip.js
- Extract the files
- Save the files (again, this is a temporary file system)
- Store a reference to them so I can display them to the user
Here is the function that handles all of that.
Once done - that leaves us with the simple job of providing basic interaction with the images. This is done via buttons that allow for navigation.
And that's it! Before I link to the demo, I'll warn you that this is not very tolerant of browsers that don't support everything required. Here are a few screen shots though to give you an idea of how it works.
First up - the application as it looks on loading.

Next - I drag a CBZ file over it...

And then it gets to work. Now - this part can be a bit slow. To be fair, I dragged a 35 megabyte file into the browser and it took about 40 seconds to parse. I think that's fairly decent for JavaScript.

I also provide UI feedback as the images are saved.

And then finally - the comic is readable. (Whether or not the story is any good is another question.)

Want to try it out? Hit the demo link below. Note that you may want to try with the latest Chrome and with a small comic. I've created a simple "comic" out of a zip of pictures that can be downloaded here.
Edit on 2/2/2018: Due to the age of the demo, and the fact that the File API is deprecated, I've removed the online demo. You can still download the code, but I would not recommend using it as is. Rather, you could unzip the binary data into IndexedDB. You can download the code here: https://static.raymondcamden.com/enclosures/2012_05_28.zip
Archived Comments
Hey, this is really cool. I am a programmer at USC and was wondering if I can perhaps as you a couple questions in regards to the comic book reader. Is there anyway i can contact you via email. I would really like to add a similar feature to a project I am working on :)
You may absolutely email me. Use the Contact link on top.
When I drop the demo comic into the reader it just downloads it again... I'm using the most recent version of chrome in windows XP.
That sounds like the drag/drop handler isn't working. Can you try a simpler version of the code that _just_ has that portion and see if it still works?
Raymond,
I'm stuck on campus with my girlfriend, trying to read Amazing Spider-Man #232 on these locked down iMacs. I was surprised to find that the best web-based cbz reader I could find was your weekend project! However, since it was a weekend project, the code still lacks some features I would really love. Would you mind if I forked your code, and started adding some features? I would post all my code on GitHub and credit your blog post in the readme, or I could fork it from your GitHub account or even work on your branch if you would like to upload it. All up to you.
Specifically, I was going to add fit-to-width, fit-to-height, two page spreads, and keyboard controls. Maybe I would work on adding a "library" feature later, for people to run their own private version.
That would be cool. Let me setup a GitHub repo tomorrow you can fork and contribute too.
Awesome!
I've been working on it since my comment ( minus a long dinner ), and I already have fit to width / height working, key commands working, and I'm almost done with full spread!
You can check it out at http://rkuykendall.com/uplo...
The key bindings are arrows ( or j/k ), v/h, and f.
Looking forward to committing my code!
Hey Raymond, how is it going?
Doh! Been packed. :) Ok, time to get this into GitHub NOW!
Done. And thanks for reminding me: https://github.com/cfjedima...
Hi!
I really like your reader. I'm trying to build a comic reader for iOS using PhoneGap 2.9, just for learning purposes. do you think that's doable?. Maybe I could use some of this code??.
Thanks!!
Afaik you can not use the FileSystem API in Mobile Safari. I just checked:
http://caniuse.com/#feat=fi...
iOS7 is marked as unknown.
Just realized the link from my last comment is broken and I have long since finished my additions. Thanks again for adding a repo, Raymond.
Comic reader:
http://rkuykendall.com/webs...
GitHub Respoitory:
https://github.com/rkuykend...
Blog post:
http://rkuykendall.com/arti...
Just out of curiosity, is there any way to implement .cbr? The majority of my comics for some reason are in .cbr rather than .cbz. Or are there any converters out there?
Otherwise loving the simplicity of it over all.
@Kevin: I did some research, and apparently RAR isn't a standard, so there aren't any good OS libraries out there. The best I found when I looked last time (admittedly a while ago) was a Java library that could read a list of entries from the RAR but not actually extract anything.
Thanks for the answer! I'll try with xCode then.
My own comic book reader in the browser: https://code.google.com/p/k...
Binary tools for JS library you might find interesting: https://code.google.com/p/b...
Oh nice, you got CBR support working? Mind if I borrow that? :)
It's an open source library, so of course not :)
How are you? Did you ever get any parts working???
@Bill: What?
Hey folks - the new version may be found here: https://www.raymondcamden.c...