Welcome!

ColdFusion Authors: Yakov Fain, Pat Romanski, Liz McMillan, Maureen O'Gara, Greg Ness

Related Topics: ColdFusion

ColdFusion: Article

File Upload Utility with ColdFusion

File Upload Utility with ColdFusion

ColdFusion is, arguably, the preeminent database middleware for NT-based Web sites. Somewhere around version 3.1 Allaire began calling their product an Application Server, implying it was more than middleware. In fact, ColdFusion 3.1 has a wealth of tags that are not related to database access. In addition, it provides a function library rich enough to remind veteran C programmers of the Standard Library – in design and intention at least, if not quite in breadth and depth.

I'll touch on several types of tags in the example application, but Table 1 summarizes the most powerful of them, which I call the utility tags. The function library includes string-handling routines, date/ time functions, math functions, HTML and URL formatting, Boolean functions and much more. In short, the power to write Web-hosted versions of useful utilities is built in. I want to illustrate the use of some of the tags with a sample file upload application.

The Need for This Application
A digital imaging service bureau was receiving hundreds of megabytes of imaging files daily from their clients. They found that they needed to offer three or four different file transfer services so clients could pick the method that worked for them. "How," they asked me, "can we build a simple user-friendly file upload facility that everyone can use – Macintosh and Windows users, Photoshop fanatics and FTP experts alike?" They especially wanted people to stop attaching 35 MB TIFF files to e-mail, choking the mail server. It would also be nice to be notified about the upload so that rush jobs could be pounced on rather than languish in the upload directory for minutes at a time.

The browser seemed like the obvious starting point. Netscape Navigator's FTP client already allowed file uploads, and although it has a friendly drag-and-drop interface, it tended to baffle most first-timers. Besides, not everyone was using Navigator. A familiar applicationlike interface was needed, with form fields and an Upload button, a form that would work with any modern browser. The service bureau was already running ColdFusion for database access and they knew we could do a lot with the function library. We decided to take a look at those mysterious <CF> utility tags.

The HTML Form
The result was a file upload application based in ColdFusion. It consisted of an HTML form on the front end and a ColdFusion template at the back. As a courtesy to users, JavaScript opens a small floating window displaying the HTML upload screen (see Figure 1). This leaves the main browser window available for users who want to browse other screens during long uploads. The main browser window also displays a message for users of incompatible browsers, including alternate upload instructions. (See default.htm in the program listings.)

At the heart of the form is the file type input field, here named FileContents, which presents a text field and a browse button to the user. This little-known input type is not specific to ColdFusion in any way; rather, it is a 3.2 addition to the HTML specification. The full path of the file to be uploaded must be entered into the text box by typing or browsing. When the form is submitted, instead of submitting the filename as text, the browser opens the file and streams its contents to the server as the value of the FileContents field. For this to work, the form's ENCTYPE must be set to "multipart/form-data" within the <FORM> tag. Stripped to its barest essentials, the form looks like Listing 1. (The complete HTML code is in UploadForm.htm in the program listings.)

The server must have a receiving process that is prepared to deal with this filestream; ColdFusion provides such a process. It is invoked by the <CFFILE> tag, as I'll demonstrate. The remainder of the form consists of two text input fields and a pair of radio buttons. The text fields, ClientName' and ClientPhone', provide identifying information to accompany the uploaded file. The radio button pair, named NameConflict', will be used to instruct <CFFILE> on how to handle potential filename conflicts on the server.

The ColdFusion Application
Now let's dissect the server side of the application (see UploadFile.cfm in the program listings). ColdFusion has the <CFSET> tag for creating and initializing variables in server space. We begin the application by defining several variables that will be used as constants later on. This is just good programming practice. Putting these constants at the top of the template makes it easy to change them later, easier than if we had embedded the text strings at various places deep in the file. C programmers will recognize this as similar to the #define usage of that language. Alternatively, these text values could easily be kept in the database to be looked up in a ColdFusion query. Either way, we assign the values to variables, with <CFSET>, for later use in the program.

<cfset incoming = "e:\ftproot\incoming">
<cfset mailserver = "mail.tinyflashunit.com">
<cfset jobs_email = "jobs@tinyflashunit.com">
<cfset phonenum = "612-555-1212">

Next we set up a global error handler with the <CFERROR> tag; here Basic programmers will recognize a construct similar to On Error GoTo' in that language.

<cferror type="request"
template="catastrophic.cfm"
mailto="#fail_email#"
>

In the event of a catastrophic error anywhere in the file, <CFERROR> aborts processing of the current page and transfers control to the named error-handling template, catastrophic.cfm in this case. All we're allowed to pass is an e-mail address to respond to, but within the error handler a variety of error status variables are exposed. These may be dereferenced as #Error.StatusVar#. Together with the provided e-mail address, the status variables can be used to construct an intelligent error message for the user. A minimalist example is included in the source code listings as catastrophic.cfm.

We're really just trapping unforeseen critical errors here, such as disk-full on the server, so we can return some kind of message to users rather than leave them hanging.

After the error handler is established, we come to the heart of the application.

<cffile action="upload"
filefield="Form.FileContents"
destination="#incoming#"
nameconflict="#Form.NameConflict#"
>

<CFFILE> is an extremely flexible tag that, through its "action" attribute, will allow you to perform almost any file-handling chore on the Web server. Here we're using the Upload action to receive the filestream being sent by the browser; the other possible actions are Move, Copy, Delete, Read, Write, Rename and Append.

Notice that we're passing the name of the form field, Form.FileContents, as the "filefield" parameter and not dereferencing it with #...#. <CFFILE> wants to know the name of the form field containing the filestream and will deal with it from there. Dereferencing #Form.FileContents# yields only a useless temp filename on the server.

The destination parameter is the name of the disk directory on the server where we want the file to reside. We assign the value of the variable, incoming, which we have previously set to hold a directory name. The "nameconflict" parameter tells <CFFILE> how to handle an upload when the same filename already exists in the destination directory. The two possible values are Overwrite and MakeUnique, and we let the uploader state his or her preference with the form radio buttons.

On completion of the <CFFILE> Upload action, a host of status variables will be set; they may be dereferenced as #File.StatusVar#. We need to save several of them for later use as the values may be erased by subsequent invocations of <CFFILE>.

<cfset UploadSuccess = #File.FileWasSaved#>
<cfset FileWasRenamed = #File.FileWasRenamed#>
<cfset FileWasOverwritten = #File.FileWasOverwritten#>
<cfset NewFileName = #File.ServerFile#>

Now there's a housekeeping chore to take care of, and we need to exercise another action of the versatile <CFFILE> tag, the Rename action. If the uploaded filename already exists on the server and the uploader has requested the MakeUnique option on the form, <CFFILE> will create a new, arbitrary filename for the file just uploaded. This is not quite what we want. To preclude confusion, we'd prefer that the new file arrive with the uploader's original filename intact. We'll put our status variables to work here. Using ColdFusion's RandRange() function, the original conflicting filename is renamed by appending an additional extension in the form of a random three-digit number. Then the newly uploaded file can be renamed to the original filename. Listing 2 shows the conditional code.

Following a successful upload we'll generate two responses. A simple HTML response is returned to the client browser, informing the uploader that the file has been received. Then an e-mail notification is generated to inform the receiving party that a file has been uploaded by a customer. This latter job is handled by another ColdFusion tag, <CFMAIL>, that allows us to compose and send a mail message – in this case, of our saved status variables and the ClientName and ClientPhone form information (see Listing 3).

An upload failure is handled in exactly the same dual-response manner. See the source code listings for the failure code.

Summary
This sample application only scratches the surface of the capabilities that Allaire has provided. Do you want to build a Web-hosted version of a favorite network utility? Chances are that you can, with ColdFusion.

We could add a lot of automation to this simple file upload utility. We could write session results to an activity file, or log them to the database. Given login rights, <CFFTP> can forward uploaded files to any FTP server in the world. Using <CFSCHEDULE> we could automate an hourly, daily or weekly cleanup of the upload directory. Uploaded text files can be read, parsed, word-counted and displayed using the built-in string library.

If you're already using ColdFusion for database access, reserve your CGI programming in C or Perl for the particularly tough nuts; in many cases a little rapid development with ColdFusion will do the job.

More Stories By Matt Newberry

Matt Newberry, an Internet database consultant in
Minneapolis and St. Paul, specializes in Web site
database integration with ColdFusion, Active Server
Pages and Java Server Pages. He can be reached at matt@tinyflashunit.com

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.