Using Per-Application Mappings With File I/O In ColdFusion
Months ago, I had tweeted that I wished that per-application mappings in ColdFusion worked with file I/O operations, like fileRead() and fileWrite(). In response to said tweet, Tony Nelson replied that you can use the mappings with file I/O as long as you use it in conjunction with expandPath(). Unfortunately, I completely forgot this conversation until last week when I blogged about using expandPath() with ColdFusion's per-application mappings.
Since this is an awesome feature of the language, and one that I wasn't deeply aware of, I thought I should put together a quick demonstration. In the following app, I'm mapping a "storage" directory; then, I'm writing to and reading from it, respectively.
Application.cfc - Setting Up The Per-Application Mappings
<cfscript>
component
output = false
hint = "I define the application settings and event handlers."
{
// Define the application settings.
this.name = hash( getCurrentTemplatePath() );
this.applicationTimeout = createTimeSpan( 0, 0, 10, 0 );
// Get the base directory so we can set up relative mappings.
this.directory = getDirectoryFromPath( getCurrentTemplatePath() );
// Set up a mapping for "storage". Notice that the actual directory
// name is "data."
this.mappings[ "/storage" ] = ( this.directory & "data/" );
}
</cfscript>
Notice that we set up a "/storage" mapping for the "data" directory. Now, we're going to write from and then read from that mapping:
Index.cfm - Our Test Page
<cfscript>
logFile = ( timeFormat( now(), "HH-mm-ss" ) & ".txt" );
// Log the request.
writeDump(
var = cgi,
format = "text",
output = expandPath( "/storage/#logFile#" )
);
// Gather the files in the "storage" directory.
filePaths = directoryList( expandPath( "/storage" ) );
// Output the file names so we can see which directory is actually
// storing the files mapped via "/storage".
for ( filePath in filePaths ) {
writeOutput( filePath & "<br />" );
}
</cfscript>
Here, I'm logging the CGI scope on each request and then listing the contents of the mapped directory. Notice that each file I/O operation uses the mapped directory; but, it passes through the expandPath() function first.
When we run the above code, we get the following page output:
/Sites/bennadel.com/testing/expand-path-io/data/08-44-20.txt
/Sites/bennadel.com/testing/expand-path-io/data/08-49-13.txt
/Sites/bennadel.com/testing/expand-path-io/data/08-49-14.txt
/Sites/bennadel.com/testing/expand-path-io/data/09-05-24.txt
Notice that the "/storage" mapping successfully mapped to the "data" directory.
This is one of those features that should have been part of my core understanding of the ColdFusion language. Unfortunately it was not; but, fortunately, it's never too late to learn. This is a very powerful feature and one that I will certainly take joy in using.
Want to use code from this post? Check out the license.
Reader Comments
Ben,
expandPath() on missing files/directories that use an IIS virtual directory resolves incorrectly in CF10. I just blogged about it if you want to link to my post.
expandPath() on missing files/directories that use a ColdFusion mapping has been fixed in CF10 (was a non-issue in CF9).
I don't advocate using an IIS virtual directory inside CF code, but that's the legacy environment I've inherited for the time being.
@Chris,
Feel free to link to your post! For sure! I don't have a lot of experience with virtual-directories, so I wouldn't be able to say one way or the other what works with them.
Definitely, though, I've used expandPath() a *lot* with missing files, outside of virtual directories. For example, when testing things, I'll usually have something like:
And, the first run of the page, "log.txt" doesn't work. But, usually when testing things like this, I'm not using CF mappings.
That said, I'll stay away from virtual mappings :D
@Ben,
Thanks for allowing me to post the link.
@Everyone,
Here's the link to my blog post explaining the expandPath() VD issue:
http://cfweller.blogspot.com/2013/09/cf10-expandpath-issue-with-iis-virtual.html