Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the New York ColdFusion User Group (Sep. 2009) with:

Learning ColdFusion 8: CFZip Part V - Deleting Zip File Archives

By Ben Nadel on
Tags: ColdFusion

In the previous parts of this series, we looked at how to make, read, and extract zip archive files using ColdFusion 8's new CFZip and CFZipParam tags. Now, let's finish this up taking a quick look at how we can delete entries within a zip archive. I'm not talking about deleting the actual Zip file - that would best be done using CFFile - I'm talking about deleting items within the archive file. Since this is, by far, the least interesting of all the actions, I am gonna try to keep this brief.

As always, before we can start exploring the deleting of an archive in ColdFusion 8, we have to create a zip archive to work with. We are going to zip the following directory structure:

./data/documents/manual.txt
./data/documents/readme.txt
./data/images/funny.jpg
./data/images/mud_monster.jpg
./data/images/red_face.jpg
./data/images/smile.jpg

To create the zip, we are going to use the simple ColdFusion 8 CFZip tag:

  • <!---
  • Create a zip archive of the data directory.
  • By default, ColdFusion 8 will recurse the
  • source directory, store the storage paths,
  • and do to our use of Overwrite attribute, we
  • will make sure we create a new zip archive.
  • --->
  • <cfzip
  • action="zip"
  • source="#ExpandPath( './data/' )#"
  • file="#ExpandPath( './data.zip' )#"
  • overwrite="true"
  • />

This will put all contents of the data directory into the root of our zip archive (the documents and images directory). Now that have a zip archive, the easiest thing we can do is delete everything inside of it using the delete action:

  • <!--- Delete all contents of the Zip archive. --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#"
  • />

Ok, maybe not. This action actually throws the following ColdFusion error:

Cannot delete all the entries from a zip file. There should be at least one entry remaining in the zip file.

When deleting zip archive entries in ColdFusion 8, you have to be careful to leave at least one entry. This also helps us to draw the conclusion that ColdFusion 8 does not allow you have empty directory entries in the archive (despite the fact that listing archive entries can have a type of Directory). In order to avoid this, we can modify the delete action to make sure we only delete certain files. The least destructive thing we can do is to delete a single file using the EntryPath attribute:

  • <!--- Delete the readme.txt file. --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#"
  • entrypath="documents/readme.txt"
  • />

Here, we are deleting the readme.txt file located within the documents folder. As with zip archive extracting, the EntryPath attribute cannot start with the "./" or "/" path constructs. Again, ColdFusion 8 will not thrown any error, it simply won't see the file you are referring to.

To make the action slightly more destructive, we can delete an entire folder by using an EntryPath that references a directory entry:

  • <!--- Delete the documents directory. --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#"
  • entrypath="documents"
  • />

Here, we are deleting the entire documents folder. And again, this EntryPath must not start or end with any "/" path constructs or ColdFusion will simply not find the entry you are referring to.

When we start to delete multiple files at once, as we just did above, we can use the Filter attribute to selectively include files in our zip modification. As we have discussed many times before, the Filter file mask can use the wild card * as well as take a comma delimited list of file masks. In this next example, we will delete entries in the documents folder, but only those that are manuals:

  • <!---
  • Delete any manual files that are located
  • within the documents directory.
  • --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#"
  • entrypath="documents"
  • filter="manual*"
  • />

This will delete the manual.txt but it will leave the readme.txt file in place.

By default, all delete actions on the zip archive are recursive. That means that if a directory has subdirectories, ColdFusion 8 will delete all files and folders in the target entrypath directory. Therefore, if we simply remove the EntryPath from the example above:

  • <!---
  • Delete any manual files that are located
  • anywhere within the zip archive.
  • --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#"
  • filter="manual*"
  • />

... we will end up with the same exact result (deleting the manual.txt file in the documents folder). This is because removing the EntryPath will point the delete action at the root of the archive. Then, since ColdFusion 8 zip actions are recursive by default, it will eventually recurse through the subfolders (documents and images) and find the manual.txt file to delete.

To turn off recursive delete, simply set the Recurse attribute to False. This will ensure that only the FILES within the target directory will be deleted and that the subdirectories will not be touched.

As with all CFZip actions, deleting can also be done by using the CFZip tag in conjunction with nested CFZipParam tags. EntryPath, Filter, and Recurse can all be moved into one or more CFZipParam tags. Remember that each CFZipParam tag represents an action; therefore, the Filter attribute of one CFZipParam tag applies only to itself and to no other sibling tags. The same is true for Recurse and EntryPath. To mimic the manual.txt deletion above, we can move the appropriate attributes down into a child tag:

  • <!---
  • Delete any manual files that are located
  • anywhere within the zip archive.
  • --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#">
  •  
  • <!--- Delete manual files. --->
  • <cfzipparam filter="manual*" />
  •  
  • </cfzip>

And of course, we can have more than one CFZipParam tag. In this next example, we will delete the manual files and the entire images directory:

  • <!---
  • Delete any manual files that are located
  • anywhere within the zip archive. Also delete
  • the entire images directory.
  • --->
  • <cfzip
  • action="delete"
  • file="#ExpandPath( './data.zip' )#">
  •  
  • <!--- Delete manual files. --->
  • <cfzipparam filter="manual*" />
  •  
  • <!--- Delete the images directory. --->
  • <cfzipparam entrypath="images" />
  •  
  • </cfzip>

This will leave us with a zip archive that has just one entry:

./documents/readme.txt

So there you have it. Sorry if this part of the series was a bit brief, but I think we have beaten ColdFusion 8's new CFZip tag into the ground. On top of that, I think deleting zip entries is going to be used the least of all the actions.




Reader Comments

Hi Ben, hi all,

Correct me if I'm wrong, cfZip (CF9) still can't handle password protected archives?

Reply to this Comment

Thought password protected archives were quite common nowadays.

- Can't use cfFtp to make explicit secure connections work, the documentation being not clear at all.
- Can't use cfZip to decrypt (multipart) archives because simply not supported...

I've been developing CF apps for over 10 years and I don't mean to rant, but I think Adobe should do a better job finishing good features rather than implement hype stuff with questionable benefit.

:-\

Reply to this Comment

@Gov,

Adobe has spent a lot of time in the last few years really adding a lot more features. I've heard rumors that some of the future releases are really going to go back an concentrate on doing just that - beefing up the features that are already there. Here's wishing :)

Reply to this Comment

Hi Ben !!
How can I make so that an user selects various files and the system returned the compressed files?

Without the system makes a compressed file in the files system, only create a compressed file and that automatically it is downloaded to the user.

Please, excuse me my bad english, I only speak Spanish :(

Thanks for you excelent web site!

Ariel

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.