Here is a quick ColdFusion tip I hope people find useful. Let's say you have a site where users upload files. You may store all these files in one main assets folder. Doing so though could lead to a very large folder, and after time could actually impact performance. What about creating dynamic folders based on the date? So if a user uploads a file today, it would be moved to assetroot/2009/6/10. Here is a quick example of that.
First, our code needs to determine what the folder name for the current date should be. Normally I would begin with an "assets" folder, but for this example, I'll consider the root folder to be the same folder as the CFM:
<cfset folder = getDirectoryFromPath(getCurrentTemplatePath())>
To create the date based folder, I'll use the format described above - year/month/day.
<cfset newFolder = folder & "/" & year(now()) & "/" & month(now()) & "/" & day(now())>
Remember from my Cross Operating System Guide that the forward slash works perfectly across all operating systems. No need to worry about \ versus /.
Now we need to see if this folder already exists. If multiple people are uploading files, you only need to create the folder once:
<cfif not directoryExists(newFolder)>
<cfdirectory action="create" directory="#newFolder#">
</cfif>
What's nice is - even if the year folder, or month folder, doesn't exist, ColdFusion will create them for you. If the year and month folders exist, ColdFusion will just create the day folder.
Finally, you just need to move the file. If you were using cffile to process the upload, you could use the destination attribute. In my sample code, I just used a hard coded file.
<cfset fileToMove = expandPath("./missing.jpg")>
<cfset fileMove(fileToMove,newFolder & "/" & getFileFromPath(fileToMove))>
I pointed to a file in the same folder, missing.jpg, and used the fileMove function. Note how I get the file from the complete source path and use the newFolder attribute.
Here is the complete template (with a few additional outputs for testing):
<cfset folder = getDirectoryFromPath(getCurrentTemplatePath())>
<cfset newFolder = folder & "/" & year(now()) & "/" & month(now()) & "/p" & day(now())>
<cfoutput>new folder is #newFolder#<br/></cfoutput>
<cfif not directoryExists(newFolder)>
nope, doesn't exist<br/>
<cfdirectory action="create" directory="#newFolder#">
</cfif>
<cfset fileToMove = expandPath("./missing.jpg")>
<cfset fileMove(fileToMove,newFolder & "/" & getFileFromPath(fileToMove))>
Archived Comments
This is a very slick tip. I've done something similar with images and categories (not just making folders by date). I guess I did not do the mental math to know that CF would handle the folder creation if 2 of the 3 parts already existed, but its one of those "of course it will" moments.
Nick - to be clear, I did NOT think it would. Maybe it didn't in CF7 or 6. I seem to remember having to 'walk the path', in fact, I was planning on it for the blog entry. If someone is on 7 or 6 and wants to test, I'd love to see it. And if you and I right that it changed, I'll do an example of that.
Wow! You're right. I just did a quick test on CF 8 where I created a directory with 3 other directories inside of it. I know for a fact that this didn't work before, because I've had to create a java object and use mkdirs() to get it to work in the past. But, at that time we were actually running CF 6, 7, and 8 servers so I don't remember which one it was....
Good find!
CF7 will create the necessary directories.
Someone want to find a CF6 server and test? I think we can stop there and not worry about CF5. ;)
Just tested on CF 6 and while the fileMove breaks it creates the file structure perfectly. Even if part of it has already been created.
Must have been 5 or 4 that had problems with walking directory structure...
Thanks for testing Daniel, Gary.
This is like two ColdFusion Quickies in one entry:
- the slick example
- and finding out cfdirectory will create more than one directory
:)
@sam: I am aim to please.
Hey, why not use DateFormat(Now(),"yyyy/mm/dd") for the date part of the pathname?
Because that would be simpler. ;)
Posting this solution in case you have a ton of files to organize: http://www.37signals.com/sv...