- CFML Reference User Guide
- ColdFusion functions
- ColdFusion functions by category
- Functions a-b
- Abs
- ACos
- AddSOAPRequestHeader
- AddSOAPResponseHeader
- AjaxLink
- AjaxOnLoad
- ApplicationStop
- ArrayAppend
- ArrayAvg
- ArrayClear
- ArrayContains
- ArrayContainsNoCase
- ArrayDelete
- ArrayDeleteAt
- ArrayDeleteNoCase
- ArrayEach
- ArrayFilter
- ArrayFind
- ArrayFindAll
- ArrayFindAllNoCase
- ArrayFindNoCase
- ArrayInsertAt
- ArrayIsDefined
- ArrayIsEmpty
- ArrayLen
- ArrayMap
- ArrayMax
- ArrayMin
- ArrayNew
- ArrayPrepend
- ArrayReduce
- ArrayResize
- ArraySet
- ArraySetMetadata
- ArraySlice
- ArraySort
- ArraySum
- ArraySwap
- ArrayToList
- Asc
- ASin
- Atn
- AuthenticatedContext
- AuthenticatedUser
- BinaryDecode
- BinaryEncode
- BitAnd
- BitMaskClear
- BitMaskRead
- BitMaskSet
- BitNot
- BitOr
- BitSHLN
- BitSHRN
- BitXor
- BooleanFormat
- Abs
- Functions-c-d
- CacheGet
- CacheGetAllIds
- CacheGetMetadata
- CacheGetProperties
- CacheGetSession
- CacheIdExists
- CachePut
- CacheRegionExists
- CacheRegionNew
- CacheRegionRemove
- CacheRemove
- CacheRemoveAll
- CacheSetProperties
- CallStackDump
- CallStackGet
- CanDeSerialize
- Canonicalize
- CanSerialize
- Ceiling
- CharsetDecode
- CharsetEncode
- Chr
- CJustify
- Compare
- CompareNoCase
- Cos
- CreateDate
- CreateDateTime
- CreateObject
- CreateObject: .NET object
- CreateObject: COM object
- CreateObject: component object
- CreateObject: CORBA object
- CreateObject: Java or EJB object
- CreateObject: web service object
- CreateODBCDate
- CreateODBCDateTime
- CreateODBCTime
- CreateSignedJWT
- CreateEncryptedJWT
- CreateTime
- CreateTimeSpan
- CreateUUID
- CSRFGenerateToken
- CSRFVerifyToken
- CSVRead
- CSVWrite
- CSVProcess
- DateAdd
- DateCompare
- DateConvert
- DateDiff
- DateFormat
- DatePart
- DateTimeFormat
- Day
- DayOfWeek
- DayOfWeekAsString
- DayOfYear
- DaysInMonth
- DaysInYear
- DE
- DecimalFormat
- DecodeForHTML
- DecodeFromURL
- DecrementValue
- Decrypt
- DecryptBinary
- DeleteClientVariable
- Deserialize
- DeserializeJSON
- DeserializeXML
- DirectoryCopy
- DirectoryCreate
- DirectoryDelete
- DirectoryExists
- DirectoryList
- DirectoryRename
- DollarFormat
- DotNetToCFType
- Duplicate
- Functions-e-g
- EncodeForCSS
- EncodeForDN
- EncodeForHTML
- EncodeForHTMLAttribute
- EncodeForJavaScript
- EncodeForLDAP
- EncodeForURL
- EncodeForXML
- EncodeForXMLAttribute
- EncodeForXpath
- Encrypt
- EncryptBinary
- EntityDelete
- EntityLoad
- EntityLoadByExample
- EntityLoadByPK
- EntityMerge
- EntityNew
- EntityReload
- EntitySave
- EntityToQuery
- Evaluate
- Exp
- ExpandPath
- FileClose
- FileCopy
- FileDelete
- FileExists
- FileGetMimeType
- FileIsEOF
- FileMove
- FileOpen
- FileRead
- FileReadBinary
- FileReadLine
- FileSeek
- FileSetAccessMode
- FileSetAttribute
- FileSetLastModified
- FileSkipBytes
- FileUpload
- FileUploadAll
- FileWrite
- FileWriteLine
- Find
- FindNoCase
- FindOneOf
- FirstDayOfMonth
- Fix
- Floor
- FormatBaseN
- GeneratePBKDFKey
- GenerateSecretKey
- GetApplicationMetadata
- GetAuthUser
- GetBaseTagData
- GetBaseTagList
- GetBaseTemplatePath
- GetClientVariablesList
- GetComponentMetaData
- GetContextRoot
- GetCPUUsage
- GetCurrentTemplatePath
- GetCSPNonce
- GetDirectoryFromPath
- GetEncoding
- GetException
- GetFileFromPath
- GetFileInfo
- GetFreeSpace
- GetFunctionCalledName
- GetFunctionList
- GetGatewayHelper
- GetHttpRequestData
- GetHttpTimeString
- GetK2ServerDocCount
- GetK2ServerDocCountLimit
- GetLocale
- GetLocaleDisplayName
- GetLocalHostIP
- GetMetaData
- GetMetricData
- GetPageContext
- GetPropertyString
- GetPropertyFile
- GetPrinterInfo
- GetPrinterList
- GetProfileSections
- GetProfileString
- GetReadableImageFormats
- GetSafeHTML
- GetSAMLAuthRequest
- GetSAMLLogoutRequest
- Generate3DesKey
- GenerateSAMLSPMetadata
- GetSOAPRequest
- GetSOAPRequestHeader
- GetSOAPResponse
- GetSOAPResponseHeader
- GetSystemFreeMemory
- GetSystemTotalMemory
- GetTempDirectory
- GetTempFile
- GetTemplatePath
- GetTickCount
- GetTimeZoneInfo
- GetToken
- GetTotalSpace
- GetUserRoles
- GetVFSMetaData
- GetWriteableImageFormats
- Functions-h-im
- Hash
- HMac
- Hour
- HQLMethods
- HTMLCodeFormat
- HTMLEditFormat
- IIf
- ImageAddBorder
- ImageBlur
- ImageClearRect
- ImageCopy
- ImageCreateCaptcha
- ImageCrop
- ImageDrawArc
- ImageDrawBeveledRect
- ImageDrawCubicCurve
- ImageDrawLine
- ImageDrawLines
- ImageDrawOval
- ImageDrawPoint
- ImageDrawQuadraticCurve
- ImageDrawRect
- ImageDrawRoundRect
- ImageDrawText
- ImageFlip
- ImageGetBlob
- ImageGetBufferedImage
- ImageGetEXIFMetadata
- ImageGetEXIFTag
- ImageGetHeight
- ImageGetIPTCMetadata
- ImageGetIPTCTag
- ImageGetMetadata
- ImageGetWidth
- ImageGrayscale
- ImageInfo
- ImageMakeColorTransparent
- ImageMakeTranslucent
- ImageNegative
- ImageNew
- ImageOverlay
- ImagePaste
- ImageRead
- ImageReadBase64
- ImageResize
- ImageRotate
- ImageRotateDrawingAxis
- ImageScaleToFit
- ImageSetAntialiasing
- ImageSetBackgroundColor
- ImageSetDrawingColor
- ImageSetDrawingStroke
- ImageSetDrawingTransparency
- ImageSharpen
- ImageShear
- ImageShearDrawingAxis
- ImageTranslate
- ImageTranslateDrawingAxis
- ImageWrite
- ImageWriteBase64
- ImageXORDrawingMode
- Functions-in-k
- IncrementValue
- InputBaseN
- Insert
- Int
- InterruptThread
- InvalidateOauthAccesstoken
- Invoke
- InitSAMLAuthRequest
- InitSAMLLogoutRequest
- InvokeCFClientFunction
- IsArray
- IsAuthenticated
- IsAuthorized
- IsBinary
- IsBoolean
- IsClosure
- IsCustomFunction
- IsDate
- IsDateObject
- IsDDX
- IsDebugMode
- IsDefined
- IsImage
- IsImageFile
- IsInstanceOf
- IsIPv6
- IsJSON
- IsK2ServerABroker
- IsK2ServerDocCountExceeded
- IsK2ServerOnline
- IsLeapYear
- IsLocalHost
- IsNull
- IsNumeric
- IsNumericDate
- IsObject
- isOnline
- IsPDFArchive
- IsPDFFile
- IsPDFObject
- IsProtected
- IsQuery
- isSamlLogoutResponse
- isSafeHTML
- IsSimpleValue
- IsSOAPRequest
- IsSpreadsheetFile
- IsSpreadsheetObject
- IsStruct
- isThreadInterrupted
- IsUserInAnyRole
- IsUserInRole
- IsUserLoggedIn
- IsValid
- IsValidOauthAccesstoken
- IsWDDX
- IsXML
- IsXmlAttribute
- IsXmlDoc
- IsXmlElem
- IsXmlNode
- IsXmlRoot
- JavaCast
- JSStringFormat
- Functions-l
- LCase
- Left
- Len
- ListAppend
- ListChangeDelims
- ListContains
- ListContainsNoCase
- ListDeleteAt
- ListEach
- ListFilter
- ListFind
- ListFindNoCase
- ListFirst
- ListGetAt
- ListGetDuplicates
- ListInsertAt
- ListLast
- ListLen
- ListMap
- ListPrepend
- ListQualify
- ListReduce
- ListRemoveDuplicates
- ListRest
- ListSetAt
- ListSort
- ListToArray
- ListValueCount
- ListValueCountNoCase
- LJustify
- Location
- Log
- Log10
- LSCurrencyFormat
- LSDateFormat
- LSDateTimeFormat
- LSEuroCurrencyFormat
- LSIsCurrency
- LSIsDate
- LSIsNumeric
- LSNumberFormat
- LSParseCurrency
- LSParseDateTime
- LSParseEuroCurrency
- LSParseNumber
- LSTimeFormat
- LTrim
- Functions-m-r
- Max
- Mid
- Min
- Minute
- Month
- MonthAsString
- Now
- NumberFormat
- ObjectEquals
- ObjectLoad
- ObjectSave
- OnWSAuthenticate
- ORMClearSession
- ORMCloseAllSessions
- ORMCloseSession
- ORMEvictCollection
- ORMEvictEntity
- ORMEvictQueries
- ORMExecuteQuery
- ORMFlush
- ORMFlushall
- ORMGetSession
- ORMGetSessionFactory
- ORMIndex
- ORMIndexPurge
- ORMReload
- ORMSearch
- ORMSearchOffline
- ParagraphFormat
- ParameterExists
- ParseDateTime
- Pi
- PrecisionEvaluate
- ProcessSAMLResponse
- ProcessSAMLLogoutRequest
- Quarter
- PreserveSingleQuotes
- QueryAddColumn
- QueryAddRow
- QueryConvertForGrid
- QueryExecute
- QueryFilter
- QueryGetResult
- QueryGetRow
- QueryKeyExists
- QueryMap
- QueryNew
- QueryReduce
- QuerySetCell
- QuotedValueList
- QueryEach
- Rand
- Randomize
- RandRange
- ReEscape
- REFind
- REFindNoCase
- ReleaseComObject
- REMatch
- REMatchNoCase
- RemoveCachedQuery
- RemoveChars
- RepeatString
- Replace
- ReplaceList
- ReplaceNoCase
- REReplace
- REReplaceNoCase
- RestDeleteApplication
- RestSetResponse
- RestInitApplication
- Reverse
- Right
- RJustify
- Round
- RTrim
- Functions-s
- Second
- SendGatewayMessage
- SendSAMLLogoutResponse
- Serialize
- SerializeJSON
- SerializeXML
- SessionInvalidate
- SessionRotate
- SessionGetMetaData
- SessionInvalidate
- SessionRotate
- SetDay
- SetEncoding
- SetHour
- SetLocale
- SetMonth
- SetProfileString
- SetPropertyString
- SetVariable
- SetYear
- Sgn
- Sin
- Sleep
- SpanExcluding
- SpanIncluding
- SpreadsheetAddAutoFilter
- SpreadsheetAddColumn
- SpreadsheetAddFreezePane
- SpreadsheetAddImage
- SpreadsheetAddInfo
- SpreadsheetAddPageBreaks
- SpreadsheetAddRow
- SpreadsheetAddRows
- SpreadsheetAddSplitPane
- SpreadsheetCreateSheet
- SpreadsheetDeleteColumn
- SpreadsheetDeleteColumns
- SpreadsheetDeleteRow
- SpreadsheetDeleteRows
- SpreadsheetFormatCell
- SpreadsheetFormatColumn
- SpreadsheetFormatCellRange
- SpreadsheetFormatColumn
- SpreadsheetFormatColumns
- SpreadsheetFormatRow
- SpreadsheetFormatRows
- SpreadsheetGetCellComment
- SpreadsheetGetCellFormula
- SpreadsheetGetCellValue
- SpreadsheetGetColumnCount
- SpreadsheetInfo
- SpreadsheetMergeCells
- SpreadsheetNew
- SpreadsheetRead
- SpreadsheetReadBinary
- SpreadsheetRemoveSheet
- SpreadsheetSetActiveSheet
- SpreadsheetSetActiveSheetNumber
- SpreadsheetSetCellComment
- SpreadsheetSetCellFormula
- SpreadsheetSetCellValue
- SpreadsheetSetColumnWidth
- SpreadsheetSetFooter
- SpreadsheetSetHeader
- SpreadsheetSetRowHeight
- SpreadsheetShiftColumns
- SpreadsheetShiftRows
- SpreadsheetWrite
- StreamingSpreadsheetNew
- StreamingSpreadsheetCleanup
- StreamingSpreadsheetRead
- StreamingSpreadsheetProcess
- SpreadsheetSetFooterImage
- SpreadsheetSetHeaderImage
- SpreadsheetSetFittoPage
- SpreadsheetUngroupColumns
- SpreadsheetGroupColumns
- SpreadsheetUngroupRows
- SpreadsheetGroupRows
- SpreadsheetRemoveColumnBreak
- SpreadsheetSetColumnBreak
- SpreadsheetRemoveRowBreak
- SpreadsheetSetRowBreak
- SpreadsheetRemovePrintGridlines
- SpreadsheetAddPrintGridlines
- SpreadsheetGetColumnWidth
- SpreadsheetSetColumnHidden
- SpreadsheetSetRowHidden
- SpreadsheetisColumnHidden
- SpreadsheetisRowHidden
- SpreadsheetisStreamingXmlFormat
- SpreadsheetisXmlFormat
- SpreadsheetisBinaryFormat
- SpreadsheetRenameSheet
- SpreadsheetRemoveSheetNumber
- SpreadsheetGetLastRowNumber
- SpreadsheetGetPrintOrientation
- Sqr
- StripCR
- StructAppend
- StructClear
- StructCopy
- StructCount
- StructDelete
- StructEach
- StructFilter
- StructFind
- StructFindKey
- StructFindValue
- StructGet
- StructGetMetadata
- StructInsert
- StructIsEmpty
- StructKeyArray
- StructKeyExists
- StructKeyList
- StructMap
- StructNew
- StructReduce
- StructSetMetadata
- StructSort
- StructToSorted
- StructUpdate
- StructValueArray
- StoreSetMetadata
- StoreGetACL
- StoreGetMetadata
- StoreAddACL
- StoreSetACL
- Functions-t-z
- Tan
- ThreadJoin
- ThreadTerminate
- Throw
- TimeFormat
- ToBase64
- ToBinary
- ToScript
- ToString
- Trace
- Transactionandconcurrency
- TransactionCommit
- TransactionRollback
- TransactionSetSavePoint
- Trim
- UCase
- URLDecode
- URLEncodedFormat
- URLSessionFormat
- Val
- ValueList
- VerifyClient
- Week
- Wrap
- WriteDump
- WriteLog
- WriteOutput
- WSGetAllChannels
- WSGetSubscribers
- WSPublish
- WSSendMessage
- XmlChildPos
- XmlElemNew
- XmlFormat
- XmlGetNodeType
- XmlNew
- XmlParse
- XmlSearch
- XmlTransform
- XmlValidate
- Year
- YesNoFormat
- ColdFusion tags
- ColdFusion tag summary
- ColdFusion tags by category
- Application framework tags
- Communications tags
- Database manipulation tags
- Data output tags
- Debugging tags
- Exception handling tags
- Extensibility tags
- File management tags
- Flow-control tags
- Forms tags
- Internet Protocol tags
- Page processing tags
- Security tags
- Variable manipulation tags
- Other tags
- Tags a-b
- Tags c
- cfcache
- cfcalendar
- cfcase
- cfcatch
- cfchart
- cfchart tag in ColdFusion
- Get started with cfchart
- Customize a chart using cfchart
- Advanced cfchart customization options
- Create an area chart in ColdFusion
- Create line charts in ColdFusion
- Create bar charts in ColdFusion
- Create floating bar charts in ColdFusion
- Create histograms in ColdFusion
- Create pie charts in ColdFusion
- Create funnel charts in ColdFusion
- Create pyramid charts in ColdFusion
- Create curve charts in ColdFusion
- Create boxplots in ColdFusion
- Create donut charts in ColdFusion
- Create bubble charts in ColdFusion
- Create scatterplots in ColdFusion
- Create radar charts in ColdFusion
- Other chart types in ColdFusion (Cone, Cylinder, Piano, and Bullet)
- Advanced customization options in cfchart
- cfchartdata
- cfchartseries
- cfchartset
- cfclient
- cfclientsettings
- cfcol
- cfcollection
- cfcomponent
- cfcontent
- cfcontinue
- cfcookie
- Tags f
- cffeed
- cffile
- cffile action = "append"
- cffile action = "copy"
- cffile action = "delete"
- cffile action = "move"
- cffile action = "read"
- cffile action = "readBinary"
- cffile action = "rename"
- cffile action = "upload"
- cffile action = "uploadAll"
- cffile action = "write"
- cffileupload
- cffinally
- cfflush
- cfform
- cfformgroup
- cfformitem
- cfftp
- cfftp: Connection: file and directory operations
- cfftp: Opening and closing FTP server connections
- cfftp : Opening and closing secure FTP server connections
- cfftp action = "listDir"
- cffunction
- Tags g-h
- Tags i
- Tags j-l
- cfjava
- cflayout
- cflayoutarea
- cfldap
- cflocation
- cflock
- cflog
- cflogin
- cfloginuser
- cflogout
- cfloop
- cfloop : conditional loop
- cfloop : index loop
- cfloop : looping over a COM collection or structure
- cfloop : looping over a date or time range
- cfloop : looping over a list, a file, or an array
- cfloop : looping over a query
- Tags m-o
- cfmail
- cfmailparam
- cfmailpart
- cfmap
- cfmapitem
- cfmediaplayer
- cfmenu
- cfmenuitem
- cfmessagebox
- cfmodule
- cfNTauthenticate
- cfoauth
- cfobject
- cfobject: .NET object
- cfobject: COM object
- cfobject: component object
- cfobject: CORBA object
- cfobject: Java or EJB object
- cfobject: web service object
- cfobjectcache
- cfoutput
- Tags p-q
- Tags r-s
- Tags t
- Tags u-z
- CFML Reference
- Reserved words and variables
- Ajax JavaScript functions
- Ajax JavaScript functions
- Function summary Ajax
- ColdFusion.Ajax.submitForm
- ColdFusion.Autosuggest.getAutosuggestObject
- ColdFusion.Layout.enableSourceBind
- ColdFusion.MessageBox.getMessageBoxObject
- ColdFusion.ProgressBar.getProgressBarObject
- ColdFusion.MessageBox.isMessageBoxDefined
- JavaScriptFunctionsinColdFusion9Update1
- ColdFusion ActionScript functions
- ColdFusion mobile functions
- Application.cfc reference
- Script functions implemented as CFCs
- ColdFusion Flash Form style reference
- Styles valid for all controls
- Styles for cfform
- Styles for cfformgroup with horizontal or vertical type attributes
- Styles for box-style cfformgroup elements
- Styles for cfformgroup with accordion type attribute
- Styles for cfformgroup with tabnavigator type attribute
- Styles for cfformitem with hrule or vrule type attributes
- Styles for cfinput with radio, checkbox, button, image, or submit type attributes
- Styles for cftextarea tag and cfinput with text, password, or hidden type attributes
- Styles for cfselect with size attribute value of 1
- Styles for cfselect with size attribute value greater than 1
- Styles for cfcalendar tag and cfinput with dateField type attribute
- Styles for the cfgrid tag
- Styles for the cftree tag
- ColdFusion Flash Form Style Reference
- ColdFusion event gateway reference
- ColdFusion Event Gateway reference
- addEvent
- CFEvent
- CFEventclass
- Constructor
- Gateway development interfaces and classes
- getStatus
- setCFCPath
- setCFCMethod
- getOriginatorID
- getLogger
- getBuddyList
- getBuddyInfo
- IM gateway message sending commands
- IM Gateway GatewayHelper class methods
- onIncomingMessage
- onIMServerMessage
- onBuddyStatus
- onAddBuddyResponse
- onAddBuddyRequest
- IM Gateway CFC incoming message methods
- IM gateway methods and commands
- CFML CFEvent structure
- warn
- info
- setOriginatorID
- data command
- submit Multi command
- submit command
- setGatewayType
- setGatewayID
- setData
- setCFCListeners
- outgoingMessage
- getStatusTimeStamp
- numberOfMessagesReceived
- numberOfMessagesSent
- removeBuddy
- removeDeny
- removePermit
- setNickName
- setPermitMode
- setStatus
- SMS Gateway CFEvent structure and commands
- SMS Gateway incoming message CFEvent structure
- getStatusAsString
- getProtocolName
- getPermitMode
- getPermitList
- getNickName
- getName
- getDenyList
- getCustomAwayMessage
- getQueueSize
- getMaxQueueSize
- getHelper
- getGatewayType
- getGatewayServices
- getGatewayID_1
- getGatewayID
- getData
- getCFCTimeout
- setCFCTimeout
- getCFCPath
- getCFCMethod
- GatewayServices class
- Gateway interface
- GatewayHelper interface
- addPermit
- addDeny
- addBuddy
- error
- debug
- Logger class
- stop
- start
- CFML event gateway SendGatewayMessage data parameter
- restart
- fatal
- SMS gateway message sending commands
- ColdFusion C++ CFX Reference
- ColdFusion Java CFX reference
- WDDX JavaScript Objects
- Cloud services
- ColdFusion and GCP Storage
- ColdFusion and GCP Firestore
- ColdFusion and GCP PubSub
- ColdFusion and Amazon S3
- ColdFusion and DynamoDB
- ColdFusion and Amazon SQS
- ColdFusion and Amazon SNS
- ColdFusion and MongoDB
- ColdFusion and Azure Blob
- ColdFusion and Azure Service Bus
- Multi-cloud storage services
- Multi-cloud RDS databases
- ColdFusion and Azure Cosmos DB
Description
Manages interactions with server files. The following sections describe the actions of the cffile tag:
- cffile action = "append"
- cffile action = "copy"
- cffile action = "delete"
- cffile action = "move"
- cffile action = "read"
- cffile action = "readBinary"
- cffile action = "rename"
- cffile action = "upload"
- cffile action = "uploadAll"
-
Note: To execute, this tag must be enabled in the ColdFusion Administrator. For more information, see Configuring and Administering ColdFusion.
If your ColdFusion applications run on a server used by multiple customers, consider the security of the files that could be uploaded or manipulated by cffile . For more information, see Configuring and Administering ColdFusion.
Category
Syntax
The tag syntax depends on the action attribute value. See the following sections.
See also
History
ColdFusion 10: Modifications to the attribute accept
ColdFusion 9: uploadAll action
ColdFusion 8: Support for reading and writing cfimages .
ColdFusion MX 7:
- Added the result attribute, which allows you to specify an alternate variable in which to receive result parameters. Used for action = "upload" action.
- Added the fixnewline attribute for action = "append" and action = "write" actions.
ColdFusion MX 6.1: - Changed file path requirements: if you do not specify an absolute file path, the path is relative to the ColdFusion temporary directory, which is returned by the GetTempDirectory function.
- Changed behavior for action="read": if the file starts with a byte order mark (BOM) ColdFusion uses it to determine the character encoding.
- Changed behavior for action="upload" nameConflict="MakeUnique" ColdFusion now makes filenames unique by appending a incrementing number, 1 for the first file, 2 for the second and so on, to the name. In ColdFusion, filenames were made unique by appending an additional "1" for each file, as in 1, 11, 111, and so on.
ColdFusion MX: - Changed use of slashes in paths: you can use forward or backward slashes in paths on both UNIX and Windows systems.
- Changed file hierarchy requirements: ColdFusion does not require that you put files and directories that you manipulate with this tag below the root of the web server document directory.
- Changed directory path requirements for the destination attribute: a directory path that you specify in the destination attribute does not require a trailing slash.
- Deprecated the system value of the attributes attribute.
- Deprecated the temporary value of the attributes attribute. In ColdFusion, it is a synonym for normal. It might not work in later releases.
- Changed the action attribute options read, write, append and move: they support a new attribute, charset.
- The archive value of the attributes attribute is obsolete and has no effect.
Provide file content in the tag body
For cffile action = "append" and cffile action = "write", you can provide file content in the tag body. If you provide file content in both the tag body and the output attribute, it results in an error. In the following example, the text provided in the body is written to myfile.txt in the current directory.Now assume that the file does not exist, then a new file myfile.txt is created. If the file exists, it is overwritten.
<cfset filename = expandpath('./myfile.txt')> |
Similarly, if you use cffile action="append", the tag body content is appended to the contents of the file myfile.txt. To create an empty file, you have to provide at least a blank line in the tag body as shown in the following code:
<!--- Leave a blank line here---> |
Modifications to the attribute accept in ColdFusion 10
The attribute accept takes comma-separated list of any or all extensions, MIME type, or list of MIME types as values. Specify the extensions with a . prefix. That is, only .txt is supported and not txt, *.txt, or *.*. However, you can use * as a wildcard to accept all files.
- If you specify filename extension as value, the file is checked, only to ensure if it matches the list of extensions you specified in comma-separated list. If it matches, the file is uploaded.
- If the value is MIME type or list of MIME types and the attribute strict is set to true, then the first few bytes of the file are read to determine the MIME type. If MIME type matches with what you have specified, upload occurs, else results in an error. The default value of strict is true.
- If you specify both filename extensions and MIME types and if strict is set to false, the verification is based on the order in which you have specified the values. For example, if the first value is .txt, then the .txt file is uploaded.
If strict is set to true, extensions are ignored.
Example: Using the attribute accept to verify the filename extension
upload.cfm
<cfset variables.URL = "http://#cgi.server_name#:#cgi.server_port## |
_upload.cfm
<!--- create upload directory ---> |
In this example, accept is set to .txt and strict is not specified (and therefore is true by default). So, only files with .txt extensions are considered for upload.Even if the file is originally a PDF (sample.pdf) renamed as sample.txt, the file is uploaded (since strict is not set to true).
If you specify strict=true, then if the file is originally a .txt (and not renamed from some other type) the file is uploaded only if the correct MIME type is specified. That is, strict=true requires MIME type to be specified in the accept attribute. So, you should explicitly say accept="text/plain" in _upload.cfm.
Example 2: Using MIME type
Modify the Example 1 by specifying accept="application/pdf" in _upload.cfm as follows:
destination="#uploadDirectory#" |
Since strict = true, only files of type PDF are considered for upload. To use a different file, modify the following section of upload.cfm:
<cfhttpparam type="FILE" name="myfile" file="#expandpath('./sample.txt')#"> |
Example 3: Using both extension and MIME type
Modify the Example 1 by specifying the following in _upload.cfm:
action="UPLOAD" |
Only PDF files are uploaded because strict = true. If you set strict as false, then both the files are uploaded.
To use a different file, modify the following snippet of upload.cfm:
<cfhttpparam type="FILE" name="myfile" file="#expandpath('./sample.txt')#"> |
Example
| This is a view-only example. ---> <!--- <cfif IsDefined("form.formsubmit") is "Yes"> <!--- The form has been submitted, now do the action. ---> <cfif form.action is "new"> <!--- Make a new file. ---> <cffile action="Write" file="#GetTempDirectory()#foobar.txt" output="#form.the_text#"> </cfif> <cfif form.action is "read"> <!--- Read existing file. ---> <cffile action="Read" file="#GetTempDirectory()#foobar.txt" variable="readText"> </cfif> <cfif form.action is "add"> <!--- Update existing file. ---> <cffile action="Append" file="#GetTempDirectory()#foobar.txt" output="#form.the_text#"> </cfif> <cfif form.action is "delete"> <!--- Delete existing fil. ---> <cffile action="Delete" file="#GetTempDirectory()#foobar.txt"> </cfif> </cfif> <!--- Set some variables. ---> <cfparam name="fileExists" default="no"> <cfparam name="readText" default=""> <!--- First, check whether canned file exists. ---> <cfif FileExists("#GetTempDirectory()#foobar.txt") is "Yes"> <cfset fileExists="yes"> </cfif> <!--- Now, make the form that runs the example. ---> <form action="index.cfm" method="POST"> <h4>Type in some text to include in your file:</h4> <p> <cfif fileExists is "yes"> <p>A file exists (foobar.txt, in <cfoutput>#GetTempDirectory()#</cfoutput>). You may add to it, read from it, or delete it. </p> </cfif> <!--- If reading from a form, let that information display in textarea. ---> <textarea name="the_text" cols="40" rows="5"> <cfif readText is not ""> <cfoutput>#readText#</cfoutput> </cfif></textarea> <!--- Select from the actions depending on whether the file exists. ---> <select name="action"> <cfif fileExists is "no"> <option value="new">Make new file </cfif> <cfif fileExists is "yes"> <option value="add">Add to existing file <option value="delete">Delete file <option value="read">Read existing file </cfif> </select> <input type="Hidden" name="formsubmit" value="yes"> <input type="Submit" name="" value="make my changes"> </form> ---> |
Real-world uses of the cffile tag
File upload with validation
Your document management system allows users to upload important business documents like contracts, invoices, and proposals. For security and storage management, you need to validate file types, restrict file sizes, prevent malicious uploads, and organize files properly.
Problem statement
- Users need to upload various document types (PDF, Word, Excel)
- Must validate file types to prevent malicious uploads
- Need to enforce file size limits (e.g., max 10MB)
- Files should be renamed to prevent conflicts
- Must provide clear feedback on upload success/failure
- Need to organize files by user or category
- Security requires validating actual file content, not just extensions
Solution
Use cffile with the `action="upload"` to handle file uploads with comprehensive validation.
<cfscript>
// Configuration
uploadDir = expandPath("./uploads/");
maxFileSize = 10485760; // 10MB in bytes
allowedTypes = "application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
// Create upload directory if it doesn't exist
try {
if (!directoryExists(uploadDir)) {
directoryCreate(uploadDir);
}
canUpload = true;
} catch (any e) {
canUpload = false;
uploadDir = "File system access not available";
}
</cfscript>
<h2>Secure File Upload with Validation</h2>
<cfif NOT canUpload>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ File Upload Not Available</h3>
<p>The application doesn't have permission to create upload directories.</p>
<p><strong>For production:</strong> Configure a directory with proper write permissions.</p>
</div>
</cfif>
<!--- Upload Form --->
<cfif NOT isDefined("form.documentFile") AND canUpload>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3>Upload Document</h3>
<p>Accepted file types: PDF, Word (.doc, .docx), Excel (.xls, .xlsx)</p>
<p><strong>Maximum file size:</strong> 10 MB</p>
</div>
<form method="post" enctype="multipart/form-data">
<div style="margin: 20px 0;">
<label for="documentFile"><strong>Select File:</strong></label><br>
<input type="file" name="documentFile" id="documentFile" required>
</div>
<div style="margin: 20px 0;">
<label for="category"><strong>Category:</strong></label><br>
<select name="category" id="category">
<option value="contracts">Contracts</option>
<option value="invoices">Invoices</option>
<option value="proposals">Proposals</option>
<option value="other">Other</option>
</select>
</div>
<div>
<button type="submit" style="padding: 10px 20px; background: ##2196f3; color: white; border: none; border-radius: 5px; cursor: pointer;">
Upload Document
</button>
</div>
</form>
<cfelseif isDefined("form.documentFile") AND canUpload>
<!--- Process File Upload --->
<h3>Processing Upload...</h3>
<cftry>
<!--- Upload the file with validation --->
<cffile
action="upload"
fileField="documentFile"
destination="#uploadDir#"
nameConflict="makeunique"
accept="#allowedTypes#"
strict="true"
result="uploadResult">
<!--- Get file information --->
<cfset uploadedFilePath = uploadResult.serverDirectory & "/" & uploadResult.serverFile>
<cfset fileInfo = getFileInfo(uploadedFilePath)>
<!--- Validate file size --->
<cfif uploadResult.fileSize GT maxFileSize>
<!--- File too large, delete it --->
<cffile action="delete" file="#uploadedFilePath#">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: red; margin: 0;">✗ Upload Failed</h3>
<p><strong>Error:</strong> File size exceeds maximum allowed size.</p>
<p><strong>File size:</strong> #numberFormat(uploadResult.fileSize / 1024 / 1024, "0.00")# MB</p>
<p><strong>Maximum allowed:</strong> #numberFormat(maxFileSize / 1024 / 1024, "0.00")# MB</p>
</div>
<cfelse>
<!--- Upload successful --->
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: green; margin: 0;">✓ Upload Successful!</h3>
<p>Your file has been uploaded successfully.</p>
</div>
<!--- Display upload details --->
<h3>Upload Details</h3>
<cfdump
var="#uploadResult#"
label="Upload Result"
expand="yes">
<h3>File Information</h3>
<cfscript>
uploadDetails = {};
uploadDetails.originalFilename = uploadResult.clientFile;
uploadDetails.serverFilename = uploadResult.serverFile;
uploadDetails.fileSize = numberFormat(uploadResult.fileSize / 1024, "0.00") & " KB";
uploadDetails.mimeType = uploadResult.contentType & "/" & uploadResult.contentSubType;
uploadDetails.fileExtension = uploadResult.serverFileExt;
uploadDetails.uploadDate = dateTimeFormat(fileInfo.lastModified, "yyyy-mm-dd HH:nn:ss");
uploadDetails.category = form.category;
uploadDetails.fileSaved = uploadResult.fileWasSaved;
</cfscript>
<cfdump
var="#uploadDetails#"
label="File Details"
expand="yes">
<!--- In production, save upload info to database --->
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4>💡 Production Note</h4>
<p>In a production environment, you would:</p>
<ul>
<li>Save file metadata to database</li>
<li>Associate file with user ID</li>
<li>Run virus scanning on uploaded file</li>
<li>Generate download/access tokens</li>
<li>Log upload activity for audit</li>
</ul>
</div>
</cfif>
<p><a href="?" style="padding: 10px 20px; background: ##2196f3; color: white; text-decoration: none; border-radius: 5px; display: inline-block; margin-top: 20px;">
Upload Another File
</a></p>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: red; margin: 0;">✗ Upload Failed</h3>
<p><strong>Error:</strong> #cfcatch.message#</p>
<p><strong>Detail:</strong> #cfcatch.detail#</p>
<p>Please ensure you're uploading a valid file type.</p>
</div>
<p><a href="?">Try Again</a></p>
</cfcatch>
</cftry>
</cfif>
Log file management
Your enterprise application needs to track user activities, system errors, and important business events. Instead of using database logging (which can become very large), you maintain text-based log files that are rotated monthly. Administrators need to view recent logs, archive old logs, and append new entries.
Problem statement
- Application generates continuous log entries
- Need to append to existing log files without overwriting
- Must be able to read and display log contents
- Log files need rotation (daily, weekly, monthly)
- Old logs should be archived or deleted
- Need to track multiple log types (errors, access, audit)
- Performance: Database logging can be slow for high-volume logs
- Log files must be timestamped and organized
Solution
Use multiple `cffile` actions to manage application logs
<cfscript>
// Configuration
logDir = expandPath("./logs/");
todayDate = dateFormat(now(), "yyyy-mm-dd");
currentLogFile = logDir & "app_log_" & todayDate & ".txt";
// Create logs directory if it doesn't exist
try {
if (!directoryExists(logDir)) {
directoryCreate(logDir);
}
canAccessLogs = true;
} catch (any e) {
canAccessLogs = false;
errorMessage = e.message;
}
// Function to format log entry
function formatLogEntry(logType, message) {
timestamp = dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss");
logEntry = "#timestamp# [#uCase(logType)#] #message#" & chr(13) & chr(10);
return logEntry;
}
</cfscript>
<h2>Application Log File Management</h2>
<cfif NOT canAccessLogs>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ Log Files Not Available</h3>
<p>Unable to access log directory: <strong>#errorMessage#</strong></p>
<p>This example demonstrates the log management functionality.</p>
</div>
</cfif>
<!--- Handle form submissions --->
<cfif isDefined("form.action") AND canAccessLogs>
<cftry>
<cfif form.action EQ "addLog">
<!--- Append new log entry --->
<cfset newLogEntry = formatLogEntry(form.logType, form.logMessage)>
<!--- Check if file exists, if not create it with header --->
<cfif NOT fileExists(currentLogFile)>
<cfset logHeader = "Application Log - Started: #dateTimeFormat(now(), 'yyyy-mm-dd HH:nn:ss')#" & chr(13) & chr(10) &
"============================================" & chr(13) & chr(10)>
<cffile action="write" file="#currentLogFile#" output="#logHeader#">
</cfif>
<!--- Append the log entry --->
<cffile action="append" file="#currentLogFile#" output="#newLogEntry#">
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✓ Log Entry Added Successfully</strong>
</div>
<cfelseif form.action EQ "clearLog">
<!--- Delete current log file --->
<cfif fileExists(currentLogFile)>
<cffile action="delete" file="#currentLogFile#">
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✓ Log File Cleared Successfully</strong>
</div>
</cfif>
</cfif>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✗ Error:</strong> #cfcatch.message#
</div>
</cfcatch>
</cftry>
</cfif>
<!--- Add Log Entry Form --->
<cfif canAccessLogs>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3>Add New Log Entry</h3>
<form method="post">
<input type="hidden" name="action" value="addLog">
<div style="margin: 15px 0;">
<label for="logType"><strong>Log Type:</strong></label><br>
<select name="logType" id="logType" style="padding: 5px; width: 200px;">
<option value="info">INFO</option>
<option value="warning">WARNING</option>
<option value="error">ERROR</option>
<option value="debug">DEBUG</option>
<option value="audit">AUDIT</option>
</select>
</div>
<div style="margin: 15px 0;">
<label for="logMessage"><strong>Log Message:</strong></label><br>
<textarea name="logMessage" id="logMessage" rows="3" style="width: 100%; max-width: 600px; padding: 8px;" placeholder="Enter your log message here..." required></textarea>
</div>
<div>
<button type="submit" style="padding: 10px 20px; background: ##2196f3; color: white; border: none; border-radius: 5px; cursor: pointer;">
Add Log Entry
</button>
</div>
</form>
</div>
</cfif>
<!--- Display Current Log File --->
<cfif canAccessLogs>
<h3>Current Log File: <code>app_log_#todayDate#.txt</code></h3>
<cfif fileExists(currentLogFile)>
<!--- Read the log file --->
<cftry>
<cffile action="read" file="#currentLogFile#" variable="logContents">
<!--- Get file info --->
<cfset logFileInfo = getFileInfo(currentLogFile)>
<div style="background: ##f5f5f5; border: 1px solid ##ccc; padding: 15px; margin: 15px 0; border-radius: 5px;">
<strong>File Size:</strong> #numberFormat(logFileInfo.size / 1024, "0.00")# KB |
<strong>Last Modified:</strong> #dateTimeFormat(logFileInfo.lastModified, "yyyy-mm-dd HH:nn:ss")# |
<strong>Lines:</strong> #listLen(logContents, chr(10))#
</div>
<!--- Display log contents --->
<div style="background: ##263238; color: ##aed581; padding: 20px; border-radius: 5px; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 14px; max-height: 500px; overflow-y: auto;">
<pre style="margin: 0; white-space: pre-wrap;"><cfoutput>#htmlEditFormat(logContents)#</cfoutput></pre>
</div>
<!--- Clear log button --->
<form method="post" style="margin-top: 15px;" onsubmit="return confirm('Are you sure you want to clear this log file?');">
<input type="hidden" name="action" value="clearLog">
<button type="submit" style="padding: 10px 20px; background: ##f44336; color: white; border: none; border-radius: 5px; cursor: pointer;">
Clear Log File
</button>
</form>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 15px 0; border-radius: 5px;">
<strong>Error reading log file:</strong> #cfcatch.message#
</div>
</cfcatch>
</cftry>
<cfelse>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 15px; margin: 15px 0; border-radius: 5px;">
<strong>ℹ No log file exists for today.</strong> Add a log entry to create one.
</div>
</cfif>
</cfif>
<!--- List All Log Files --->
<cfif canAccessLogs>
<h3>Log File Archive</h3>
<cftry>
<cfset logFiles = directoryList(logDir, false, "query", "app_log_*.txt", "dateLastModified desc")>
<cfif logFiles.recordCount GT 0>
<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
<thead>
<tr style="background: ##e0e0e0;">
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Log File</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Size</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Last Modified</th>
</tr>
</thead>
<tbody>
<cfoutput query="logFiles">
<tr>
<td style="padding: 10px; border: 1px solid ##ccc;">#name#</td>
<td style="padding: 10px; border: 1px solid ##ccc;">#numberFormat(size / 1024, "0.00")# KB</td>
<td style="padding: 10px; border: 1px solid ##ccc;">#dateTimeFormat(dateLastModified, "yyyy-mm-dd HH:nn:ss")#</td>
</tr>
</cfoutput>
</tbody>
</table>
<cfelse>
<p><em>No log files found.</em></p>
</cfif>
<cfcatch type="any">
<p><em>Unable to list log files.</em></p>
</cfcatch>
</cftry>
</cfif>
Configuration file management
Your multi-tenant SaaS application stores customer-specific settings in JSON configuration files. Each client has customizable features, branding options, and integration settings. Rather than querying a database for every request, you cache configurations in text files that are read once and cached in memory for performance.
Problem statement
- Each customer needs customizable application settings
- Database queries for configuration on every request hurt performance
- Need to read, update, and write configuration files
- Settings include: branding colors, feature flags, API keys, email templates
- Must validate configuration structure before saving
- Need backup of configurations before updates
Solution
Use cffile to manage configuration files.
<cfscript>
// Configuration
configDir = expandPath("./config/");
configFile = configDir & "app_settings.json";
backupDir = configDir & "backups/";
// Create directories if they don't exist
try {
if (!directoryExists(configDir)) {
directoryCreate(configDir);
}
if (!directoryExists(backupDir)) {
directoryCreate(backupDir);
}
canAccessConfig = true;
} catch (any e) {
canAccessConfig = false;
errorMessage = e.message;
}
// Default configuration structure
function getDefaultConfig() {
config = {};
config.appName = "My ColdFusion App";
config.version = "1.0.0";
config.branding = {};
config.branding.primaryColor = "##2196f3";
config.branding.secondaryColor = "##ff9800";
config.branding.logo = "logo.png";
config.features = {};
config.features.enableChat = true;
config.features.enableNotifications = true;
config.features.enableAnalytics = false;
config.email = {};
config.email.fromAddress = "noreply@example.com";
config.email.smtpServer = "smtp.example.com";
config.email.smtpPort = 587;
config.lastUpdated = dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss");
config.updatedBy = "system";
return config;
}
// Load configuration from file
function loadConfig() {
try {
if (fileExists(configFile)) {
jsonContent = fileRead(configFile);
return deserializeJSON(jsonContent);
} else {
// Create default config if doesn't exist
defaultConfig = getDefaultConfig();
saveConfig(defaultConfig, "system", "Initial configuration");
return defaultConfig;
}
} catch (any e) {
return {error: e.message};
}
}
// Save configuration to file
function saveConfig(config, updatedBy, changeNote) {
try {
// Update metadata
config.lastUpdated = dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss");
config.updatedBy = updatedBy;
// Create backup of current config
if (fileExists(configFile)) {
backupFile = backupDir & "app_settings_" & dateFormat(now(), "yyyymmdd_HHnnss") & ".json";
fileCopy(configFile, backupFile);
}
// Serialize and save
jsonContent = serializeJSON(config);
fileWrite(configFile, jsonContent);
return {success: true, message: "Configuration saved successfully"};
} catch (any e) {
return {success: false, error: e.message};
}
}
</cfscript>
<h2>Application Configuration Management</h2>
<cfif NOT canAccessConfig>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ Configuration Not Available</h3>
<p>Unable to access configuration directory: <strong>#errorMessage#</strong></p>
<p>This example demonstrates configuration file management.</p>
</div>
</cfif>
<!--- Handle form submission --->
<cfif isDefined("form.action") AND form.action EQ "saveConfig" AND canAccessConfig>
<cftry>
<!--- Load current config --->
<cfset currentConfig = loadConfig()>
<!--- Update values from form --->
<cfset currentConfig.appName = form.appName>
<cfset currentConfig.branding.primaryColor = form.primaryColor>
<cfset currentConfig.branding.secondaryColor = form.secondaryColor>
<cfset currentConfig.features.enableChat = isDefined("form.enableChat")>
<cfset currentConfig.features.enableNotifications = isDefined("form.enableNotifications")>
<cfset currentConfig.features.enableAnalytics = isDefined("form.enableAnalytics")>
<cfset currentConfig.email.fromAddress = form.fromAddress>
<cfset currentConfig.email.smtpServer = form.smtpServer>
<cfset currentConfig.email.smtpPort = form.smtpPort>
<!--- Save configuration --->
<cfset saveResult = saveConfig(currentConfig, "admin", "Configuration updated via web interface")>
<cfif saveResult.success>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✓ Configuration Saved Successfully!</strong>
<p>A backup of the previous configuration has been created.</p>
</div>
<cfelse>
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✗ Error:</strong> #saveResult.error#
</div>
</cfif>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✗ Error:</strong> #cfcatch.message#
</div>
</cfcatch>
</cftry>
</cfif>
<!--- Load and display current configuration --->
<cfif canAccessConfig>
<cfset appConfig = loadConfig()>
<cfif structKeyExists(appConfig, "error")>
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 15px 0; border-radius: 5px;">
<strong>✗ Error loading configuration:</strong> #appConfig.error#
</div>
<cfelse>
<!--- Display current config info --->
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>Configuration File:</strong> <code>app_settings.json</code><br>
<strong>Last Updated:</strong> #appConfig.lastUpdated#<br>
<strong>Updated By:</strong> #appConfig.updatedBy#
</div>
<!--- Configuration Edit Form --->
<h3>Edit Application Settings</h3>
<form method="post">
<input type="hidden" name="action" value="saveConfig">
<!--- General Settings --->
<fieldset style="border: 1px solid ##ccc; padding: 20px; margin: 20px 0; border-radius: 5px;">
<legend style="font-weight: bold; font-size: 18px;">General Settings</legend>
<div style="margin: 15px 0;">
<label for="appName"><strong>Application Name:</strong></label><br>
<input type="text" name="appName" id="appName" value="#appConfig.appName#" style="padding: 8px; width: 300px;">
</div>
<div style="margin: 15px 0;">
<label><strong>Version:</strong></label><br>
<input type="text" value="#appConfig.version#" disabled style="padding: 8px; width: 150px; background: ##f5f5f5;">
</div>
</fieldset>
<!--- Branding Settings --->
<fieldset style="border: 1px solid ##ccc; padding: 20px; margin: 20px 0; border-radius: 5px;">
<legend style="font-weight: bold; font-size: 18px;">Branding</legend>
<div style="margin: 15px 0;">
<label for="primaryColor"><strong>Primary Color:</strong></label><br>
<input type="color" name="primaryColor" id="primaryColor" value="#appConfig.branding.primaryColor#" style="padding: 5px; width: 100px; height: 40px;">
<input type="text" value="#appConfig.branding.primaryColor#" readonly style="padding: 8px; width: 100px; margin-left: 10px;">
</div>
<div style="margin: 15px 0;">
<label for="secondaryColor"><strong>Secondary Color:</strong></label><br>
<input type="color" name="secondaryColor" id="secondaryColor" value="#appConfig.branding.secondaryColor#" style="padding: 5px; width: 100px; height: 40px;">
<input type="text" value="#appConfig.branding.secondaryColor#" readonly style="padding: 8px; width: 100px; margin-left: 10px;">
</div>
</fieldset>
<!--- Feature Flags --->
<fieldset style="border: 1px solid ##ccc; padding: 20px; margin: 20px 0; border-radius: 5px;">
<legend style="font-weight: bold; font-size: 18px;">Feature Flags</legend>
<div style="margin: 15px 0;">
<label>
<input type="checkbox" name="enableChat" #appConfig.features.enableChat ? "checked" : ""#>
<strong>Enable Live Chat</strong>
</label>
</div>
<div style="margin: 15px 0;">
<label>
<input type="checkbox" name="enableNotifications" #appConfig.features.enableNotifications ? "checked" : ""#>
<strong>Enable Notifications</strong>
</label>
</div>
<div style="margin: 15px 0;">
<label>
<input type="checkbox" name="enableAnalytics" #appConfig.features.enableAnalytics ? "checked" : ""#>
<strong>Enable Analytics Tracking</strong>
</label>
</div>
</fieldset>
<!--- Email Settings --->
<fieldset style="border: 1px solid ##ccc; padding: 20px; margin: 20px 0; border-radius: 5px;">
<legend style="font-weight: bold; font-size: 18px;">Email Configuration</legend>
<div style="margin: 15px 0;">
<label for="fromAddress"><strong>From Address:</strong></label><br>
<input type="email" name="fromAddress" id="fromAddress" value="#appConfig.email.fromAddress#" style="padding: 8px; width: 300px;">
</div>
<div style="margin: 15px 0;">
<label for="smtpServer"><strong>SMTP Server:</strong></label><br>
<input type="text" name="smtpServer" id="smtpServer" value="#appConfig.email.smtpServer#" style="padding: 8px; width: 300px;">
</div>
<div style="margin: 15px 0;">
<label for="smtpPort"><strong>SMTP Port:</strong></label><br>
<input type="number" name="smtpPort" id="smtpPort" value="#appConfig.email.smtpPort#" style="padding: 8px; width: 150px;">
</div>
</fieldset>
<!--- Submit Button --->
<div style="margin: 20px 0;">
<button type="submit" style="padding: 12px 30px; background: ##4caf50; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px;">
💾 Save Configuration
</button>
</div>
</form>
<!--- View Raw JSON --->
<h3>Raw Configuration (JSON)</h3>
<div style="background: ##263238; color: ##aed581; padding: 20px; border-radius: 5px; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 14px;">
<pre style="margin: 0;"><cfoutput>#serializeJSON(appConfig)#</cfoutput></pre>
</div>
</cfif>
</cfif>
<!--- List Configuration Backups --->
<cfif canAccessConfig>
<h3>Configuration Backups</h3>
<cftry>
<cfset backupFiles = directoryList(backupDir, false, "query", "*.json", "dateLastModified desc")>
<cfif backupFiles.recordCount GT 0>
<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
<thead>
<tr style="background: ##e0e0e0;">
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Backup File</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Size</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Created</th>
</tr>
</thead>
<tbody>
<cfoutput query="backupFiles" maxrows="10">
<tr>
<td style="padding: 10px; border: 1px solid ##ccc;"><code>#name#</code></td>
<td style="padding: 10px; border: 1px solid ##ccc;">#numberFormat(size / 1024, "0.00")# KB</td>
<td style="padding: 10px; border: 1px solid ##ccc;">#dateTimeFormat(dateLastModified, "yyyy-mm-dd HH:nn:ss")#</td>
</tr>
</cfoutput>
</tbody>
</table>
<cfif backupFiles.recordCount GT 10>
<p><em>Showing 10 most recent backups. Total: #backupFiles.recordCount#</em></p>
</cfif>
<cfelse>
<p><em>No backup files found.</em></p>
</cfif>
<cfcatch type="any">
<p><em>Unable to list backup files.</em></p>
</cfcatch>
</cftry>
</cfif>
Dynamic report generation
Your business intelligence system generates custom reports in CSV and text formats for different stakeholders. Sales managers need monthly sales reports, executives need summary reports, and data analysts need detailed exports. Reports are generated on-demand based on database queries and must be available for download or email delivery.
Problem statement
- Need to generate CSV reports from database query results
- Reports must be formatted with headers and proper delimiters
- Different report formats for different audiences (CSV, TXT, summary)
- Reports should be timestamped and uniquely named
- Need to check report generation status
Solution
Use cffile with action="write" and action="append" to generate reports.
<cfscript>
// Configuration
reportsDir = expandPath("./reports/");
// Create reports directory if it doesn't exist
try {
if (!directoryExists(reportsDir)) {
directoryCreate(reportsDir);
}
canGenerateReports = true;
} catch (any e) {
canGenerateReports = false;
errorMessage = e.message;
}
// Sample sales data (in production, this would come from database)
function getSalesData() {
salesData = queryNew("OrderID,CustomerName,Product,Quantity,UnitPrice,TotalAmount,OrderDate",
"integer,varchar,varchar,integer,decimal,decimal,date");
// Add sample rows
queryAddRow(salesData, {
OrderID: 1001,
CustomerName: "Acme Corporation",
Product: "Widget Pro",
Quantity: 50,
UnitPrice: 29.99,
TotalAmount: 1499.50,
OrderDate: createDate(2024, 10, 15)
});
queryAddRow(salesData, {
OrderID: 1002,
CustomerName: "TechStart Inc",
Product: "Gadget Plus",
Quantity: 25,
UnitPrice: 149.99,
TotalAmount: 3749.75,
OrderDate: createDate(2024, 10, 18)
});
queryAddRow(salesData, {
OrderID: 1003,
CustomerName: "Global Services Ltd",
Product: "Widget Pro",
Quantity: 100,
UnitPrice: 29.99,
TotalAmount: 2999.00,
OrderDate: createDate(2024, 10, 20)
});
queryAddRow(salesData, {
OrderID: 1004,
CustomerName: "Digital Solutions",
Product: "SuperTool X",
Quantity: 15,
UnitPrice: 299.99,
TotalAmount: 4499.85,
OrderDate: createDate(2024, 10, 22)
});
queryAddRow(salesData, {
OrderID: 1005,
CustomerName: "Enterprise Co",
Product: "Gadget Plus",
Quantity: 75,
UnitPrice: 149.99,
TotalAmount: 11249.25,
OrderDate: createDate(2024, 10, 25)
});
return salesData;
}
// Function to generate CSV content from query
function generateCSV(data) {
// Get column names
columns = data.columnList;
// Start with header row
csvContent = columns & chr(13) & chr(10);
// Add data rows
for (row in data) {
rowData = [];
for (col in listToArray(columns)) {
value = row[col];
// Escape commas and quotes in data
if (findNoCase(",", value) OR findNoCase("""", value)) {
value = """" & replace(value, """", """""", "ALL") & """";
}
arrayAppend(rowData, value);
}
csvContent &= arrayToList(rowData, ",") & chr(13) & chr(10);
}
return csvContent;
}
// Function to generate formatted text report
function generateTextReport(data) {
textContent = "===========================================================================" & chr(13) & chr(10);
textContent &= " SALES REPORT " & chr(13) & chr(10);
textContent &= "===========================================================================" & chr(13) & chr(10);
textContent &= "Generated: " & dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss") & chr(13) & chr(10);
textContent &= "Total Orders: " & data.recordCount & chr(13) & chr(10);
textContent &= "===========================================================================" & chr(13) & chr(10);
textContent &= chr(13) & chr(10);
// Calculate totals
grandTotal = 0;
for (row in data) {
grandTotal += row.TotalAmount;
}
// Add detail rows
for (row in data) {
textContent &= "Order ##" & row.OrderID & chr(13) & chr(10);
textContent &= " Customer: " & row.CustomerName & chr(13) & chr(10);
textContent &= " Product: " & row.Product & chr(13) & chr(10);
textContent &= " Quantity: " & row.Quantity & chr(13) & chr(10);
textContent &= " Unit Price: " & dollarFormat(row.UnitPrice) & chr(13) & chr(10);
textContent &= " Total: " & dollarFormat(row.TotalAmount) & chr(13) & chr(10);
textContent &= " Order Date: " & dateFormat(row.OrderDate, "yyyy-mm-dd") & chr(13) & chr(10);
textContent &= "---------------------------------------------------------------------------" & chr(13) & chr(10);
}
textContent &= chr(13) & chr(10);
textContent &= "GRAND TOTAL: " & dollarFormat(grandTotal) & chr(13) & chr(10);
textContent &= "===========================================================================" & chr(13) & chr(10);
return textContent;
}
</cfscript>
<h2>Dynamic Report Generation</h2>
<cfif NOT canGenerateReports>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ Report Generation Not Available</h3>
<p>Unable to access reports directory: <strong>#errorMessage#</strong></p>
<p>This example demonstrates report generation functionality.</p>
</div>
</cfif>
<!--- Handle report generation --->
<cfif isDefined("form.action") AND form.action EQ "generate" AND canGenerateReports>
<cftry>
<!--- Get sales data --->
<cfset salesData = getSalesData()>
<!--- Generate report based on format --->
<cfset reportDate = dateFormat(now(), "yyyy-mm-dd")>
<cfset reportTime = timeFormat(now(), "HHnnss")>
<cfif form.reportFormat EQ "csv">
<cfset reportContent = generateCSV(salesData)>
<cfset reportFileName = "sales_report_#reportDate#_#reportTime#.csv">
<cfelse>
<cfset reportContent = generateTextReport(salesData)>
<cfset reportFileName = "sales_report_#reportDate#_#reportTime#.txt">
</cfif>
<cfset reportPath = reportsDir & reportFileName>
<!--- Write report to file --->
<cffile action="write" file="#reportPath#" output="#reportContent#">
<!--- Get file info --->
<cfset reportFileInfo = getFileInfo(reportPath)>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: green; margin: 0;">✓ Report Generated Successfully!</h3>
<p><strong>Report Name:</strong> #reportFileName#</p>
<p><strong>Format:</strong> #uCase(form.reportFormat)#</p>
<p><strong>Records:</strong> #salesData.recordCount#</p>
<p><strong>File Size:</strong> #numberFormat(reportFileInfo.size / 1024, "0.00")# KB</p>
<p><strong>Generated:</strong> #dateTimeFormat(reportFileInfo.lastModified, "yyyy-mm-dd HH:nn:ss")#</p>
<!--- Download link --->
<p style="margin-top: 15px;">
<a href="reports/#reportFileName#" download style="padding: 10px 20px; background: ##2196f3; color: white; text-decoration: none; border-radius: 5px; display: inline-block;">
📥 Download Report
</a>
</p>
</div>
<!--- Preview report content --->
<h3>Report Preview</h3>
<div style="background: ##263238; color: ##aed581; padding: 20px; border-radius: 5px; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 14px; max-height: 400px; overflow-y: auto;">
<pre style="margin: 0; white-space: pre-wrap;"><cfoutput>#htmlEditFormat(reportContent)#</cfoutput></pre>
</div>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 20px 0; border-radius: 5px;">
<strong>✗ Error generating report:</strong> #cfcatch.message#
</div>
</cfcatch>
</cftry>
</cfif>
<!--- Report Generation Form --->
<cfif canGenerateReports>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3>Generate Sales Report</h3>
<form method="post">
<input type="hidden" name="action" value="generate">
<div style="margin: 15px 0;">
<label for="reportFormat"><strong>Report Format:</strong></label><br>
<select name="reportFormat" id="reportFormat" style="padding: 8px; width: 250px;">
<option value="csv">CSV (Comma-Separated Values)</option>
<option value="txt">Text (Formatted Report)</option>
</select>
</div>
<div style="margin: 15px 0;">
<p><strong>Report Will Include:</strong></p>
<ul style="margin: 5px 0;">
<li>Order ID and Customer Name</li>
<li>Product Details</li>
<li>Quantity and Pricing</li>
<li>Order Dates</li>
<li>Total Calculations</li>
</ul>
</div>
<div>
<button type="submit" style="padding: 12px 30px; background: ##4caf50; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px;">
📊 Generate Report
</button>
</div>
</form>
</div>
</cfif>
<!--- Sample Data Preview --->
<cfif canGenerateReports>
<h3>Sample Data Preview</h3>
<cfset sampleData = getSalesData()>
<cfdump
var="#sampleData#"
label="Sales Data (Sample)"
expand="yes">
</cfif>
<!--- List Generated Reports --->
<cfif canGenerateReports>
<h3>Generated Reports</h3>
<cftry>
<cfset reportFiles = directoryList(reportsDir, false, "query", "sales_report_*.*", "dateLastModified desc")>
<cfif reportFiles.recordCount GT 0>
<table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
<thead>
<tr style="background: ##e0e0e0;">
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Report Name</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Format</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Size</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: left;">Generated</th>
<th style="padding: 10px; border: 1px solid ##ccc; text-align: center;">Download</th>
</tr>
</thead>
<tbody>
<cfoutput query="reportFiles" maxrows="10">
<tr>
<td style="padding: 10px; border: 1px solid ##ccc;"><code>#name#</code></td>
<td style="padding: 10px; border: 1px solid ##ccc;">#uCase(listLast(name, "."))#</td>
<td style="padding: 10px; border: 1px solid ##ccc;">#numberFormat(size / 1024, "0.00")# KB</td>
<td style="padding: 10px; border: 1px solid ##ccc;">#dateTimeFormat(dateLastModified, "yyyy-mm-dd HH:nn:ss")#</td>
<td style="padding: 10px; border: 1px solid ##ccc; text-align: center;">
<a href="reports/#name#" download style="padding: 5px 15px; background: ##2196f3; color: white; text-decoration: none; border-radius: 3px; display: inline-block;">
📥 Download
</a>
</td>
</tr>
</cfoutput>
</tbody>
</table>
<cfif reportFiles.recordCount GT 10>
<p><em>Showing 10 most recent reports. Total: #reportFiles.recordCount#</em></p>
</cfif>
<cfelse>
<p><em>No reports generated yet. Generate your first report above.</em></p>
</cfif>
<cfcatch type="any">
<p><em>Unable to list reports.</em></p>
</cfcatch>
</cftry>
</cfif>