Here is a function that I have for wrapping the CFFile tag. Use and abuse at your own risk. I have used this as part of a DAO for tracking file metadata as well is anyone has interest. <cffunction name="fileUpload" access="public" returntype="struct" output="no" hint="Replacement for the CFFile tag with action=Upload Returns a struct with all the values as specified in the CFFile tag. Upload to a temp dir (destination) then shift the file to its finalDestination with URLSafeName=TRUE to make downloads via HTTP a sure thing
Returns a struct containing: Parameter/ Description
attemptedServerFile
Initial name ColdFusion used when attempting to save a file
clientDirectory
Directory location of the file uploaded from the client's system
clientFile
Name of the file uploaded from the client's system
clientFileExt
Extension of the uploaded file on the client system (without a period)
clientFileName
Name of the uploaded file on the client system (without an extension)
contentSubType
MIME content subtype of the saved file
contentType
MIME content type of the saved file
dateLastAccessed
Date and time the uploaded file was last accessed
fileExisted
Whether the file already existed with the same path (Yes or No)
fileSize
Size of the uploaded file
fileWasAppended
Whether ColdFusion appended uploaded file to a file (Yes or No)
fileWasOverwritten
Whether ColdFusion overwrote a file (Yes or No)
fileWasRenamed
Whether uploaded file renamed to avoid a name conflict (Yes or No)
fileWasSaved
Whether Cold Fusion saves a file (Yes or No)
oldFileSize
Size of a file that was overwritten in the file upload operation
serverDirectory
Directory of the file saved on the server
serverFile
Filename of the file saved on the server
serverFileExt
Extension of the uploaded file on the server (without a period)
serverFileName
Name of the uploaded file on the server (without an extension)
timeCreated
Time the uploaded file was created
timeLastModified
Date and time of the last modification to the uploaded file
"
usage="fileUpload(
fileField= 'form.uploadfield',
destination = 'C:\temp',
nameconflict = 'MAKEUNIQUE',
finalDestination = 'C:\myUploadDir',
URLSafeName='yes',
charset='UTF-8'
);
"
>
<cfargument name="filefield" type="string" required="Yes" hint="String naming the
form field containing the upload: FORM.myFile" />
<cfargument name="destination" type="string" required="Yes" />
<cfargument name="nameconflict" type="string" required="no" default="error" />
<cfargument name="accept" type="string" required="no" default="" />
<cfargument name="attributes" type="string" required="no" default="" />
<cfargument name="mode" type="numeric" required="no" default="777" />
<cfargument name="finalDestination" type="string" required="no"
default="#arguments.destination#" hint="Default= arguments.destination. Not part of
the CFFile tag. If included, the function will attempt to move the file to the
specified fully qualified file path." />
<cfargument name="charset" type="string" required="no" default="UTF-8" hint="Not
part of the CFFile UPLOAD attribute set. If FINALDESTINATION attribute is passed to
the function, the function will attempt to move the file to the specified fully
qualified file path and pass the value of the CHARSET attribute onto the CFFile MOVE
that it attempts." />
<cfargument name="URLSafeName" type="boolean" required="no" default="true" hint="Not
part of the CFFile UPLOAD attribute set. If set to TRUE, the function will attempt to
rename the file to clean out all special characters and spaces from the filename to
make URLs safe." />
<cfargument name="OS" type="string" allowedValues="Windows,UNIX" required="no"
default="Windows" hint="Not part of the CFFile UPLOAD attribute set. Changes the
directory separator character depending on the OS specified. If a value other than
allowed values is passed error is thrown" />
<cfargument name="createCompressedCopy" type="boolean" required="no" default="0"
hint="Not part of the CFFile UPLOAD attribute set. Creates a compressed copy of the
file with name FILENAME.FILEEXT.ZIP in the same finalDestination as the upload." />
<cfset var tempFilename = ''/>
<cfset var returnStruct = ''/>
<cfset var throwError = 0/>
<cfset var UploadedFileName ='' />
<cfset var CurrentFileName ='' />
<cfset var dirSeparator ='\' />
<cfset var UNIXSeparator ='/' />
<cfset var WindowsSeparator ='\' />
<cfset var targetFileName ='' />
<cfset var targetDir='' />
<!--- check input of arguments.nameconflict --->
<cfif isdefined('arguments.nameconflict')>
<cfif not listfindnocase('ERROR,MAKEUNIQUE,OVERWRITE,SKIP',arguments.nameconflict)>
<cfthrow type="util.tag.fileUpload" errorcode="8FDD44942AB546B78D96EE49595CFB14"
message="function fileUpload received an invalid value for NameConflict" />
</cfif>
</cfif>
<!--- Check input of arguments.OS --->
<cfswitch expression="#arguments.OS#">
<cfcase value="UNIX">
<cfset dirSeparator = UNIXSeparator/>
<cfset arguments.destination =
replace(arguments.destination,WindowsSeparator,DirSeparator,'all') />
<cfset arguments.finaldestination =
replace(arguments.finaldestination,WindowsSeparator,DirSeparator,'all') />
</cfcase>
<cfcase value="Windows">
<cfset dirSeparator = WindowsSeparator />
<cfset arguments.destination =
replace(arguments.destination,UNIXSeparator,DirSeparator,'all') />
<cfset arguments.finaldestination =
replace(arguments.finaldestination,UNIXSeparator,DirSeparator,'all') />
</cfcase>
<cfdefaultcase>
<cfthrow type="util.tag.fileUpload" errorcode="4421905C3F5648DCA9C22A05441A352F"
message='The argument "OS" must have value of "Windows", "Windows 2000" or "UNIX". You
specified "#arguments.os#"' />
</cfdefaultcase>
</cfswitch>
<!--- If the destination is a directory and not a specific file, make sure it has a
trailing slash --->
<cfif GetDirectoryfrompath(arguments.destination) neq arguments.destination and not
len(GetFilefrompath(arguments.destination) )>
<cfset arguments.destination = arguments.destination & dirSeparator />
</cfif>
<!--- If the finaldestination is a directory and not a specific file, make sure it
has a trailing slash --->
<cfif not isDefined('arguments.finaldestination')>
<cfset arguments.finaldestination = arguments.destination />
<cfelseif GetDirectoryfrompath(arguments.finaldestination) neq
arguments.finaldestination and not len(GetFilefrompath(arguments.finaldestination) )>
<cfset arguments.finaldestination = arguments.finaldestination & dirSeparator />
</cfif>
<!--- make sure destination dirs exist --->
<cfif not directoryExists(arguments.destination)>
<cfdirectory action="CREATE" directory="#arguments.destination#"
mode="#arguments.mode#" />
<cftrace category="util.tag.fileUpload" type="Information" text="Created
destination Directory" var="arguments.destination" />
</cfif>
<cfif not directoryExists(arguments.finalDestination)>
<cfdirectory action="CREATE" directory="#arguments.finalDestination#"
mode="#arguments.mode#" />
<cftrace category="util.tag.fileUpload" type="Information" text="Created
finaldestination Directory" var="arguments.finaldestination" />
</cfif>
<cfif arguments.finalDestination eq arguments.destination>
<cftrace category="util.tag.fileUpload" type="Information" text="finaldestination
eq destination. Uploading directly" var="arguments.destination" />
<cffile action="UPLOAD"
filefield="#arguments.filefield#"
destination="#arguments.destination#"
nameconflict="#arguments.nameconflict#"
accept="#arguments.accept#"
attributes="#arguments.attributes#"
mode="#arguments.mode#">
<cfset returnStruct = duplicate(cffile)>
<cfset OriginalFileName = cffile.clientFIle />
<cfset CurrentFileName = cffile.serverFIle />
<cfelse>
<!--- If a finalDestination is specified, ignore the nameconflict flag in arguments
for now --->
<cffile action="UPLOAD"
filefield="#arguments.filefield#"
destination="#arguments.destination#"
nameconflict="MAKEUNIQUE"
accept="#arguments.accept#"
attributes="#arguments.attributes#"
mode="#arguments.mode#">
<cftrace category="util.tag.fileUpload" type="Information" text="finaldestination
neq destination. File of size #cffile.filesize# File uploaded to destination:"
var="arguments.destination" />
<cfscript>
returnStruct = duplicate(cffile);
OriginalFileName = cffile.clientFIle ;
CurrentFileName = cffile.serverFIle ;
if(not len(getfilefrompath(arguments.finalDestination))){
//this is a dir only
arguments.finalDestination = arguments.finalDestination & CurrentFileName;
}
if(fileExists(arguments.finalDestination) ){
switch(arguments.nameconflict){
case "ERROR":{
throwError=1;
break;
}
case "SKIP":{
returnStruct.fileExisted = true;
returnstruct.filewassaved = false;
returnstruct.fileWasRenamed =false;
returnstruct.attemptedServerFile = getfilefrompath(arguments.finaldestination);
returnstruct.serverdirectory = getdirectoryfrompath(arguments.finaldestination);
return returnstruct;
break;
}
case "OVERWRITE":{
returnStruct.fileExisted = true;
returnstruct.filewassaved = true;
returnstruct.fileWasRenamed =false;
returnstruct.attemptedServerFile = getfilefrompath(arguments.finaldestination);
break;
}
case "MAKEUNIQUE":{
returnstruct.attemptedServerFile = getfilefrompath(arguments.finaldestination);
origfilename = getfilefrompath(arguments.finaldestination);
origdir = getdirectoryfrompath(arguments.finaldestination);
arguments.finaldestination= origDir & replace(createUUID(),'-','','ALL') & "."
& listlast(origfilename,".");
returnStruct.fileExisted = true;
returnstruct.filewassaved = true;
returnstruct.fileWasRenamed =true;
returnstruct.serverdirectory = origdir;
break;
}
}
}
</cfscript>
<cfif throwError>
<cfthrow
type="util.tag.fileUpload"
errorcode="0x47f4fa72b3e3ce4ca47f0a4f7dc0fd4c"
message="A file exists in the specified location with the specified name"
/>
</cfif>
</cfif>
<cfset targetFileName =CurrentFileName />
<cfif arguments.finalDestination neq arguments.destination>
<cftrace category="util.tag.fileUpload" type="Information" text="Moving file to
finaldestination Directory" var="arguments.finaldestination" />
<cfscript>
if (arguments.URLSafeName){
targetdir = getdirectoryfrompath(arguments.finalDestination) ;
//We made sure above that finalDestination is a fully qualifed path
targetFileName = getfilefrompath(arguments.finalDestination) ;
targetFileName = replace(targetFileName,'[^A-Za-z0-9\.]','_','ALL') ;
arguments.finalDestination = targetdir & targetFileName ;
}
this.fileMove(
source="#cffile.serverdirectory##dirSeparator##CurrentFileName#",
destination="#arguments.finalDestination#",
attributes="#arguments.attributes#",
mode="#arguments.mode#",
charset="#arguments.charset#"
);
returnstruct.serverdirectory = GetDirectoryFromPath(arguments.finalDestination);
</cfscript>
<cftrace category="util.tag.fileUpload" type="Information" text="Moved file of size
#cffile.filesize# to finaldestination Directory as:" var="cffile.serverfile" />
<cfelseif arguments.URLSafeName >
<cfset targetFileName = replace(targetFileName,'[^A-Za-z0-9\.]','_','ALL') />
<cffile action="RENAME"
source="#cffile.serverdirectory##dirSeparator##CurrentFileName#"
destination="#cffile.serverdirectory##dirSeparator##targetFileName#"
attributes="#arguments.attributes#"
mode="#arguments.mode#"
/>
<cftrace category="util.tag.fileUpload" type="Information" text='Renaming file :
source="#cffile.serverdirectory##dirSeparator##CurrentFileName#"
destination="#cffile.serverdirectory##dirSeparator##targetFileName#"
' var="cffile.filesize" />
</cfif>
<cfset returnstruct.serverfile = targetFileName />
<cfif arguments.createCompressedCopy>
<cftry>
<cfscript>
myUtil=application.components.util.udf;
zipthis=returnstruct.serverDirectory & application.dirSeparator &
returnstruct.serverfile;
intothis=zipthis & '.zip';
if(fileexists(intothis)){
this.fileDelete(intoThis);
}
</cfscript>
<cftrace category="util.tag.fileUpload" type="Information" text="Attempting to zip
file #zipthis# into #intothis#" />
<cfset myUtil.zipFile(intothis,zipthis) />
<cftrace category="util.tag.fileUpload" type="Information" text="File zipped
successfully into #intothis#" />
<cfcatch>
<cftrace category="FileUpload" type="Warning" text="Failed to create zip archive
when trying to compress uploaded file." var="zipthis" />
</cfcatch>
</cftry>
</cfif>
<cftrace category="util.tag.fileUpload" type="Information" text="Upload complete.
File uploaded to:" var="returnstruct.serverfile" />
<cfreturn returnstruct />
</cffunction>
<<winmail.dat>>
