Package multiple named files using cfzip

In ColdFusion (and in Lucee too 🙂 ) you can create ZIP files easily using cfzip. The usage is simple when you want to package a single file or the whole directory, but it gets more complicated when you think of multiple named files stored in different places. So, let’s take a look at the simple “single file” and “whole directory” examples. When creating a package, you can simply use:

<!--- single file --->
<cfzip action="zip" source="/path/to/file/zipMe.txt" file="/path/to/package/packageName.zip" />

<!--- whole directory --->
<cfzip action="zip" source="/path/to/directory/" file="/path/to/package/packageName.zip" />

But what if I want to create a ZIP file containing some named files? In some cases, I let website users select what files they want to download and I’m creating the package with all of them. In this case, I can use the default behavior of the cfzip tag, which is appending. During the “zip” action, the files are simply appended to the ZIP package. So, I can do something like this:

<cfzip action="zip" source="/path/to/file/zipMe1.txt" file="/path/to/package/packageName.zip" />
<!--- initially, the packageName.zip contains one file... --->

<cfzip action="zip" source="/path/to/file/zipMe2.txt" file="/path/to/package/packageName.zip" />
<!--- and now the packageName.zip contains two files - zipMe1.txt and zipMe2.txt --->

The above method works, but the performance in such a case is poor. On each file appended to the ZIP package, the whole package is re-created. So, there is a better method – use cfzipparam:

<cfzip action="zip" file="/path/to/package/packageName.zip">
    <cfzipparam source="/path/to/file/zipMe1.txt" />
    <cfzipparam source="/path/to/file/zipMe2.txt" />
</cfzip>

In most cases, I’m using an array or list of files to package. In such a case, my code looks like this:

<cfset listOfFiles = "/path/to/file/zipMe1.txt,/path/to/file/zipMe2.txt,/path/to/file/zipMe3.txt" >

<cfzip action="zip" file="/path/to/package/packageName.zip">
    <cfloop list="#listOfFiles#" index="fileToZip">
        <cfzipparam source="#fileToZip#">
    </cfloop>
</cfzip>

This way I can let clients chose which files to compress, the ZIP action is performant and the resulting file contains expected files.