The app I’m trying to create reads image files from a compressed file. either a zip, a rar or 7-zip format. The aim is to then extract the first image from the file and use that to make a thumbnail that can be displayed in an electron browser page.
Sounds easy? But I’ve been through lot’s of different uncompress/decompress libraries from the npm package manager and none of them have really fitted the bill. In fact the current choice I see as a bit of a compromise.
To make the app truly cross platform I was hoping for a self contained library that ran the decompression algorithms natively within Node.js/Javascript. There are a few out there, many for handling zip files, but when it comes to rar the perfomance and capabilities are really lacking.
The answer? Use a wrapper to call an external command. Having to do this I decided why end up with 3 programs to handle zip, rar and 7-zip when 7-zip will cater for all. This means I have to have the 7z executable in my PATH or my electron app will fail. It’s a sacrifice I’ll have to live with for now.
So in installed node-7z:
$ npm install node-7z
This is a snippet of the routine I’ve written to handle the processing of the file. It extract the first image, resizes it to 160px wide, converts it to a png and saves it as testfile.png
var n7z = require('node-7z'), files = [], // The array of compressed files cbr = new n7z(); cbr.list(file) // First lets get the first image file from the compressed file .progress(function(zfiles) { zfiles.forEach(function(zfile) { // Populate the array of compressed files if ('.jpg.jpeg.gif.png'.indexOf(path.extname(zfile.name)) != -1) { files.push(zfile.name); } }); }) .then(function(spec) { // Now we have finished the list extract the files cbr.extract(file, path.join(__dirname, 'temp'), { wildcards: files[0] } // we only want the first file ) .then(function() { // After it's extracted let's resize it to make a cover thumbnail const nativeImage = require('electron').nativeImage, fs = require('fs'); var coverImg = nativeImage.createFromPath(path.join(__dirname, 'temp', files[0])), // Load the image buffer = coverImg.resize({width: 160}); // Specify only a width and height is calculated from aspect ratio // Save the buffer to a file as a png (.toPng) format fs.writeFile(path.join(__dirname, 'temp', 'testfile.png'), buffer.toPng(), function(err) { console.error(err); } ) }) .catch(function(err) { console.error(err); }); }) .catch(function(err) { console.error(err); });