Ask Ben: Creating An Archive Folder / File List

Posted January 8, 2007 at 8:55 AM by Ben Nadel

Tags: ColdFusion, Ask Ben

I have a simple little app im trying to develop that will display end of the month reports. These reports are in excel format.

I need it to do two things..

1. allow upload of new excel files
2. create new archive folders for the previous month.

I can easily do 1 & 2, but my problem is getting the paths right.

the folder structure has a root folder.. say.. reports. inside that folder are the current excel (xls) files AND the archived folders (april06,may06 etc.). Inside each archived folder there are the archived .xls files for that month.

the way i started creating this little app was to add an index.cfm file to every directory, so I can link directly to the folder and it will pick up index.cfm in that folder which pretty much does the same thing like the root index.cfm. Not at all ideal, but it was working....almost..

In each index.cfm file I display all the xls files for that current directory, as well as it lists all the folders in the root directory with an href to that folder. For the inside folders, the folder link path were incorrect. they now display as http://localhost/reports/april06/april06/

so.... How can i dynamically build the folder structure so I dont have to worry about this? Also what other suggestions do you have for this? It would be nice to not have to create an index.cfm file in every folder...

Any help would be appreciated.

For this, I would just put all the navigation in the root folder. The page should start by listing out all the archive folders. Each folder link should submit back to itself and pass in the desired folder name. The page should then list out the archive documents for that folder. This way, there is only one page required to navigate the root folder AND all the sub folders. Furthermore, this does not require you to do anything when you add new archive folders.

Take a look at the page below and let me know if you have any questions:

  • <!--- Kill extra output. --->
  • <cfsilent>
  •  
  • <!---
  • This is the name of the archive folder for which we
  • want to list out the archive documents.
  • --->
  • <cfparam
  • name="URL.folder"
  • type="string"
  • default=""
  • />
  •  
  • <!--- Decode the folder value. --->
  • <cfset URL.folder = UrlDecode( URL.folder ) />
  •  
  • <!---
  • For security reasons, we want to get rid of any suspect
  • values in the folder variable. These include "../"
  • which would go to a parent directory or "/" which will
  • go to the root perhaps.
  • --->
  • <cfset URL.folder = URL.folder.ReplaceAll(
  • "(\.\.[\\/])+", ""
  • ).ReplaceAll(
  • "[\\/]+", ""
  • ) />
  •  
  • <!---
  • Set the directory path of the root archive
  • directory (this one).
  • --->
  • <cfset strRoot = ExpandPath( "./" ) />
  •  
  •  
  • <!---
  • Check to see if we have an archive folder selected.
  • If we do, then we want to query that one. If not,
  • then we want to get the list of all the archive folders.
  • Furthermore, if we have an archive folder, just
  • check to make sure the folder exists.
  • --->
  • <cfif (
  • Len( URL.folder ) AND
  • DirectoryExists( strRoot & "\" & URL.folder )
  • )>
  •  
  • <!--- Set the query path to be the archive folder. --->
  • <cfset strQueryPath = (strRoot & "\" & URL.folder) />
  •  
  • <cfelse>
  •  
  • <!---
  • We have no archive folder selected (or it did not
  • exist). Query the root directory.
  • --->
  • <cfset strQueryPath = strRoot />
  •  
  • <!---
  • Reset the folder variable so we don't get confused
  • later on.
  • --->
  • <cfset URL.folder = "" />
  •  
  • </cfif>
  •  
  •  
  • <!---
  • Query for the files / folders in the selected
  • directory (might be root OR an archive folder). When
  • sorting the directory list, we want to sort by name
  • DESC if we are listing the archive folders, but sort
  • by name ASC if we are listing out the documents.
  • --->
  • <cfdirectory
  • action="LIST"
  • directory="#strQueryPath#"
  • recurse="false"
  • sort="name #IIF( Len( URL.folder ), DE( 'ASC' ), DE( 'DESC' ) )#"
  • name="qDirectoryList"
  • />
  •  
  • </cfsilent>
  •  
  • <cfoutput>
  • <html>
  • <head>
  • <title>Document Archive</title>
  • </head>
  • <body>
  •  
  • <h1>
  • Document Archive
  • </h1>
  •  
  • <!---
  • Check to see if we have a folder value. If we do then
  • we are outputting the contents of that folder. If we do
  • not, then we are outputting the archive folder list.
  • --->
  • <cfif Len( URL.folder )>
  •  
  • <!--- We are listing out the archive documents. --->
  • <h2>
  • #URL.folder#
  • </h2>
  •  
  • <cfloop query="qDirectoryList">
  •  
  • <!---
  • Output the link to the file from the root
  • directory (since that is where we will are).
  • Include the name of the sub folder in the path.
  • --->
  • <p>
  • <a href="./#UrlEncodedFormat( URL.folder )#/#UrlEncodedFormat( qDirectoryList.name )#">#qDirectoryList.name#</a>
  • </p>
  •  
  • </cfloop>
  •  
  •  
  • <!--- Provide a link back to parent directory. --->
  • <p>
  • &laquo; <a href="#CGI.script_name#">Back To Archive</a>
  • </p>
  •  
  • <cfelse>
  •  
  • <!--- We are viewing the archive folder list. --->
  • <p>
  • Please select an archive folder to view documents:
  • </p>
  •  
  • <cfloop query="qDirectoryList">
  •  
  • <!---
  • When outputting, we only want to display
  • directories, not files (otherwise we might
  • output the index.cfm file.
  • --->
  • <cfif (qDirectoryList.Type EQ "Dir")>
  •  
  • <!---
  • For each link, submit the page back to
  • itself but pass in the requested folder
  • name.
  • --->
  • <p>
  • <a href="#CGI.script_name#?folder=#UrlEncodedFormat( qDirectoryList.name )#">#qDirectoryList.name#</a> &raquo;
  • </p>
  •  
  • </cfif>
  •  
  • </cfloop>
  •  
  • </cfif>
  •  
  • </body>
  • </html>
  • </cfoutput>



Reader Comments

Jan 8, 2007 at 9:44 AM // reply »
46 Comments

Thanks Ben!


Jan 8, 2007 at 10:11 AM // reply »
11,238 Comments

Any time dude!


Sep 27, 2007 at 6:25 PM // reply »
5 Comments

Fabulous!! I just modified and used this code on one of my sites, Ben, and it works perfectly. Man, awesome stuff. Thanks!


Dan
Oct 22, 2008 at 12:09 PM // reply »
1 Comments

I could be wrong about this, but as far as I can tell, your code will not prevent ".." from working. Additionally, it wouldn't prevent things like %system% (can't recall if that's the right env var) from working. This would allow for one upward directory traversal, or traversal to paths predefined in the environment variables. Not too big a deal, especially considering that the intended usage of this would be to display .xls files only, but it's good to know anyway, I think.


Oct 22, 2008 at 8:04 PM // reply »
11,238 Comments

@Dan,

The script actually protects against the use of "..". It's a bit hard to read because it is in a regular expression which has to escape the periods:

\.\.

However, I do not know anything about things like %system%. I am not sure if that applies to ColdFusion paths! I will have to look into that. Thanks for the concern.


Post A Comment

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.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools