Server File Management


ColdFusion provides comprehensive server-side file and directory management through a series of tags: <cffile>, <cfcontent>, and <cfdirectory>. <cffile> is responsible for creating and manipulating files; <cfcontent> is used primarily for delivering files of different MIME types from the server to users; and <cfdirectory> handles directory listings and management. Together they provide a set of tools with which you can build complex file-management applications that can be operated from a Web browser.

NOTE

As a server-side technology, ColdFusion does not allow the manipulation of files residing on the client's machine. Client-side file manipulation through a Web browser is heavily restricted, for obvious security reasons. For a user on a standard Web browser, the developer can do little more than ask for the file she would like to upload. Client-side file manipulation can be done only through client-side Java applets, ActiveX controls, or similar embedded executables within the Web browser itself. The user must authorize these programs to have additional privileges on his machine.


Working with Files

<cffile> is a very flexible tag, with features to upload, read, write, append, copy, move, and delete files on the ColdFusion server. The syntax of <cffile> is very intuitive and straightforward, but several attributes and their uses deserve some explanation.

For example, to copy a file from one location to another on the server, you would use the following syntax:

 <cffile action="COPY"         source="C:\x\sweet.txt"         destination="C:\temp\supersweet.txt"         attributes="ReadOnly,Archive"         mode="755"> 

attributes is a comma-separated list of file settings such as ReadOnly and Archived. Not specifying attributes leaves the file with the original settings.

mode is a Unix-only setting that defines permissions for a file. Valid entries correspond to the octal (not symbolic) values of the Unix chmod command. Permissions are assigned for owner, group, and other, in sequence. For example, MODE="755" gives rwxr-xr-x permissions (owner=read/write/execute, group=read/execute, other=read/execute). mode is ignored by Windows.

CAUTION

You should be careful when implementing access to <cffile> in your application. There are obvious security ramifications in allowing users to perform file management operations on the server. The ColdFusion Administrator application can specifically lock down <cffile> so that the tag cannot be used on the server at all.


A file can be read into memory as a variable using <cffile> with the read action. This variable can be processed like any other variable. The line-feed and carriage-return characters (ASCII 10 and 13 respectively) are frequently used as delimiters for each line of the file. These are referenced in ColdFusion using Chr(10) and Chr(13), as shown here:

 <!--- read the file into a variable ---> <cffile action="READ"         file="c:filesdaemonite.txt"          variable="FileText"> <!-- converting file into a more manageable array format --> <cfset aFile=ArrayNew(1)> <cfloop list="#FileText#" index="i" delimiters="#Chr(10)##Chr(13)#">  <cfset tmp=ArrayAppend(aFile, i)> </cfloop> 

The act of writing and appending to files is essential for generating static HTML content, log files, and other text files on the server. <cffile> with action="Write" creates a file and populates it with the contents of the output attribute. Appending additional lines of information is easy when you use action="Append". The ADDNEWLINE attribute, as shown in the following example, even provides a new line, making it ideal for logging:

 <cffile action="WRITE"         file="c:\files\helloboys.txt"         output="hello cruel world!"         addnewline="Yes"> 

TIP

<cffile> is fairly cumbersome in its approach to writing when the output string value is multilined or contains characters that are text delimiters. A clever approach to this problem is to use the <cfsavecontent> tag to capture a long, complex text string as a variable:

 <!--- custom tag to capture long string ---> <cfsavecontent variable="myTextString">  Wherever there is a "Crazy Date"  Or a "Dutch Wink" or three  You are bound to find plenty of haught  And a battered-sav to see! </cfsavecontent> <cffile action="WRITE"         file="c:\files\helloboys.txt"         output="#myTextString#"         addnewline="Yes"> 


TIP

ColdFusion offers a variety of useful functions for working with the server's file system. You often have to work with absolute paths, and several functions are designed to help you determine appropriate pathnames. Some useful functions include the following: FileExists(), ExpandPath(), GetCurrentTemplatePath(), and GetTemplatePath().


<cffile> can read binary files, such as an image or an executable, into a binary object variable in memory like this:

 <cffile action="ReadBinary"         file="c:\images\logo.gif"         variable="logo"> 

The returned variable can be used anywhere in your code like a normal variable. Typically, it is used in conjunction with one of the Web protocols, such as HTTP (using <cfhttp>) or SMTP (using <cfmail>), or for writing to a database (using <cfquery>). The variable is converted to ASCII using base 64 (with the ToBase64() function) and can be handled like any other string variable.

HTTP and FTP protocols will be covered in Chapter 43, "Other Internet Protocols." SMTP and <CFMAIL> will be discussed in Chapter 41, "Email Integration."


Uploading Files to the Server

Uploading files through a Web browser is a part of the HTTP protocol. The HTML interface and form post have nothing to do with ColdFusion per se. However, ColdFusion and <cffile> kick in when the form post reaches the Web server, and the uploaded file needs to be saved to the server file system.

CAUTION

Different Web browsers have varying degrees of support for the HTTP protocol. Be sure to check that your application's target audience is using a browser that fully supports file uploads.


The standard HTML form needs an additional attribute and input field in order for file uploads to work, as in this example:

 <form action="upload.cfm"       method="post"       enctype="multipart/form-data"> File to upload:<br> <input type="file" name="uploadfile" size="30"><br> <input type="submit" value="Upload that file!"> </form> 

The enctype attribute specifies the media type used to encode the form data. The default enctype is the MIME type "application/x-www-form-urlencoded", and it's such a mouthful that nobody bothers to specify it in a standard form. However, for a file upload, the media type is different, so you must nominate the appropriate MIME type, "multipart/form-data", in the enctype attribute so that the upload will work.

The <input type="file"> form field is used exclusively for uploading files. It provides a Browse button that activates an operating systemspecific dialog box for selecting a single file. You can upload multiple files at once, but each file must have its own form field of type="file", and each form field requires a unique name.

The action page for the upload form contains a <cffile> tag with action="Upload". The filefield attribute corresponds to the specific form field name in the form post for the file you are saving to the server. If multiple files are being uploaded in a single form post, you need a separate <cffile> for each uploaded file, as shown here:

 <!--- sample upload.cfm file ---> <cffile action="UPLOAD"         filefield="UploadFile"         destination="c:\temp"         nameconflict="OVERWRITE"         accept="image/gif, image/jpg"> 

If the file upload is successful, ColdFusion writes the file to the server and generates a structure of the file's details. The structure is stored in the CFFILE scope and can be accessed using CFFILE.variablename.

TIP

CFFILE is the default return structure name, unless an alternate name is specified in the result attribute.


You can use the nameconflict attribute to nominate how filename clashes will be handled. The default is Error, but you can make more interesting choices:

  • Error (default). The file is not saved, and ColdFusion aborts and returns a run-time error.

  • Skip. The file is not saved, and no error is thrown. This value is designed for custom error handling based on values in the file-upload status parameters.

  • Overwrite. This value replaces an existing file of the same name in the <cffile> destination.

  • MakeUnique. If a name conflict occurs in the destination directory, a unique filename is automatically generated for the uploaded file. This name is available in the CFFILE.ServerFile variable.

When you are managing a file library, you often might want to restrict the uploaded files to a specific set of MIME types. For example, if you are managing an image library, you may want to restrict uploaded files to those of type .gif or .jpg. The accept attribute takes a comma-separated list of valid MIME types as a value and prevents nonconforming MIME types from being uploaded.

TIP

Don't wait for the file to upload before telling your users that they have accidentally (or otherwise) uploaded a file whose MIME type is restricted. You can warn them straightaway with some client-side scripting.

Using JavaScript and the document object model of your Web browser, you can examine the string that contains the path and filename that a user is trying to upload (look for something like document. formName.uploadFieldName.value). Simply parse this string to make sure the file extension has a match within a predetermined list of valid file extensions.

Although the file extension doesn't actually confirm the file's MIME type, it's likely to catch nearly all your problems. More often than not, the file extension corresponds to a specific MIME type for that file.


You can use CFFILE.FileSize to reject a file if it is larger than a predetermined size. Unfortunately, you cannot easily determine the file size prior to uploading. If a user uploads a file that exceeds your file size restriction, he will likely have to wait until the whole file is uploaded before you give him the bad news.

TIP

File size is listed in bytes. To format the value in the more familiar kilobytes, use the following:

 #Numberformat(CFFILE.FileSize/1024)# KB. 


TIP

When a file is uploading via HTTP through a Web browser form post, no feedback is provided on progress. In other words, during the upload the user has no idea how long it has left to go.

You should always provide a detailed explanation to the user that the file may take some time to upload. Give an estimate of upload time based on file size and common connection speeds. If you have a file size restriction, always inform the user before she starts uploading her file!


Delivering Files from the Server

To deliver a file in a simple Web application, you need only a correctly qualified URL to initiate a download using HTTP. Here's an example:

 <A HREF="http://www.forta.com/sales/leads.xls">Download Leads</A> 

In more sophisticated applications, you might need to dynamically deliver a file based on a reference in a database. This problem is further complicated by the need to deliver files from an area of the directory tree that is not mapped by the Web server. In other words, the files may not be directly accessible using a URL in the Web browser. This is an absolute requirement for a secure file store, where the application needs to authenticate a user before granting access to the file store.

You can choose from three strategies for delivering files securely:

  • Deliver an existing file from the file system.

  • Create a file on the fly and deliver.

  • Create a temporary file, deliver, and clean up by deleting the temporary file.

The <cfcontent> tag specifies a MIME type header to be sent to the browser so that the file will be interpreted as something other than a normal Web page. For example, you may be delivering a comma-separated value (CSV) file or Word document. The output can be generated on the fly, or you can specify an existing file to be delivered from anywhere on the server's file system. <cfcontent> also provides the option of deleting the file being delivered, which is perfect for cleaning up temporary files:

 <!--- for example, delivering a Word document ---> <cfcontent type="application/msword"            file="C:\FileStore\CALENDAR.DOC"            deletefile="No"> 

The strategy that you choose for file delivery will largely depend on the type of application you are building. However, all three methods run afoul of the same problem: specifying the filename of the delivered file.

Imagine that you have access to a human resources database. You need to extract a listing of employees for a specific department and deliver it as a CSV file for use in a spreadsheet program. You can build a code template called employee_list.cfm that queries the database using a URL parameter called URL.DID, then generates the appropriate CSV file:

 <!--- employee_list.cfm ---> <cfquery name="GetEmp" datasource="dsn"> SELECT * FROM Employees WHERE Department_ID = #Val(URL.DID)# </cfquery> <cfcontent type="application/unknown">"ID","LName","FName","Email" <cfoutput query="GetEmp">#EmpID#,"#LastName#","#FirstName#","#Email#" </cfoutput> 

TIP

By specifying a MIME type of "unknown", you guarantee that the Web browser will attempt to save the file to disk rather than spawn an application the Web browser believes is appropriate.


The Web browser calls a URL that ends with the filename employee_list.cfm, as you can see in this example:

http://www.forta.com/hr/employee_list.cfm?did=123

The Web browser attempts to save a file called employee_list.cfm. If you want to save a file as something like emplist.csv, you have to trick the Web browser into seeing a different filename, like this:

http://www.forta.com/hr/employee_list.cfm/emplist.csv?did=123

Note that you specify the URL parameter as usual at the end of the URL itself. The Web browser picks up the last filename specified and uses it as the filename to save as.

Alternatively, you could try using the "Content-Disposition" HTTP header as follows to specify the filename for the user:

 <cfheader name="Content-Disposition" value="inline;           filename=emplist.csv"> <cfcontent type="application/unknown">"ID","LName","FName","Email" <cfoutput query="GetEmp">#EmpID#,"#LastName#","#FirstName#","#Email#" </cfoutput> 

<CFHEADER> and <CFCONTENT> were discussed in Chapter 5, "Redirects and Reuse."


CAUTION

<cfcontent> can deliver any file from the server via the Web browser. Furthermore, the tag can be programmed to delete any file on the server. For these reasons, you must carefully consider the use of <cfcontent>. The tag can be locked down in ColdFusion Administrator to prevent any use by developers whatsoever.


Working with Directories

The <cfdirectory> list action returns a query object of files and directories from the specified directory attribute. The remaining actions of <cfdirectory> can be used to create, delete, and rename directories on the server. These actions, as shown in the following example, are straightforward in their implementation, and combined they can build quite elegant systems for managing directories on the server:

 <cfdirectory action="LIST"              directory="C:\Inetpub\wwwroot\cftrain"              name="dir"              sort="DESC"> 

TIP

Two ColdFusion functions useful for working with directories are DirectoryExists() and GetDirectoryFromPath().


TIP

Universal Naming Convention (UNC) paths on Windows and Novell Netware are possible in ColdFusion but require a few extra steps. When you install ColdFusion, the application server services, by default, start under the standard system account. This account normally has no network privileges, so network resources are unavailable to ColdFusion. If you modify the service to start under a specific named account, such as cfuser, it is possible to grant specific network privileges for that account and thereby grant ColdFusion access to network resources.

The following code snippets use functions on the UNC path for the computer elfsbane, the file share cdrive, and the directory files:

 #DirectoryExists("\\elfsbane\cdrive\files")# #FileExists("\\elfsbane\cdrive\files\test.txt")# 


CAUTION

<cfdirectory> gives developers access to the entire directory structure of the server. This potential security risk can be prevented by blocking the use of the tag through ColdFusion Administrator.




Macromedia ColdFusion MX 7 Certified Developer Study Guide
Macromedia ColdFusion MX 7 Certified Developer Study Guide
ISBN: 0321330110
EAN: 2147483647
Year: 2004
Pages: 389
Authors: Ben Forta

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net