I'm having an issue with a coldfusion11 website, under certain conditions my attempt to create and send a report file is failing, apparently due to permission issues. I can't recreate the issue on in my test/dev environment so I need to understand what is happening for a live fix, I can't just start arbitrarily changing code on production. The current code creates the file using an APPEND action like this:
<cfset f_dir = EXCEL_PATH >
<cfset f_name = CreateUUID() & ".csv">
<cffile action="APPEND" file="#f_dir##f_name#" output="My Report "
addnewline="Yes">
<cffile action="APPEND" file="#f_dir##f_name#"
output="Title,#attributes.title#" addnewline="Yes">
Elsewhere in the code are similar functions that use WRITE as the first cffile action, like this:
<cfset f_dir = EXCEL_PATH >
<cfset f_name = CreateUUID() & ".csv">
<cffile action="WRITE" file="#f_dir##f_name#" output="My Report "
addnewline="Yes">
<cffile action="APPEND" file="#f_dir##f_name#"
output="Title,#attributes.title#" addnewline="Yes">
The code that uses WRITE first is not failing, this leads to my question:
Is there a difference between creating a file with action="APPEND" and action="WRITE" in coldfusion 11?
Ron - Write is "create" - it makes a new file. Append is used to add data to an existing file on the disk. They are different actions.
Try modifying your code as follows:
<cflock name="#f_name#">
<cfif NOT fileexists(f_dir & f_name)>
... do your WRITE action>
</cfif>
</cflock>
<cflock name="#f_name#">
.... do your APPEND action - you can be sure your file exists at this point.
</cflock>
Note, I usually use a named lock to serialize these two actions. Sometimes your code trips over file handles not quite released. Not typical but if your disk is ever thrashing it can happen.
Related
The nameconflict attribute doesn't seem well documented, so maybe I'm using it wrong. But if I write a file (binary data) using the following code, it's overwriting the existing file of the same name.
<cffile action="write" file="/path/#data.name#" output="#d#" nameconflict="MakeUnique" mode="775">
nameconflict="MakeUnique" only works for <cffile action="upload".
Overwriting the file is default behavior for <cffile action="write"
Unless exact file names are not needed for display purpose it is better approach to use a unique ID as the filename to make sure we do not overwrite files.
<cfset newFile = '/path/' & CreateUUID() & '.' & ListLast(data.name, '.')>
<cffile action="write" file="#newFile#" output="#d#" mode="775">
Note: For use cases where we need to have a custom file name for view purposes, its better to save that original file name in the database and keep the filename in the filesystem in separate column.
I am having a hard time figuring out how to use cfschedule and hope someone can help get me unstuck.
I can schedule a task fine. The Admin portal indicates that the task has run, but I don't see that anything has happened.
<cfschedule
action="update"
task="update_printer_status"
operation="HTTPRequest"
startDate="03/26/2018"
startTime="12:00 PM"
url="http://localhost:8000/source/update_status.cfm"
interval="1800" />
For testing purposes, I am just trying to get it to save the date/time it runs into a log file. But the log file is empty. Here's my log file.
<!--- Read in existing contents of file --->
<cffile
action="read"
file = "c:\temp\update_log.txt"
variable = "file_contents"
>
<!--- Set additional content --->
<cfset br = chr(13) & chr(10) />
<cfset date="#DateFormat(Now())#, #TimeFormat(Now())#">
<!--- Write string back to log file --->
<cfset update_string="#file_contents##br#Update initiated: #date#">
<cfscript>
FileWrite("update_string", "#update_string#");
ustr = FileRead("update_string");
FileWrite("c:\temp\update_log.txt", "#ustr#");
</cfscript>
Can anyone tell me what I'm doing wrong here?
My issue is that I had saved my module in a protected directly. Since the context is not logged, the administrator was not seeing it.
To resolve, I just moved my file to a public directory.
I am trying to fix some code for a client. The issue is, we have .CSV files that are being written in ColdFusion but duplicates are constantly being generated for some reason, even with nameConflict = "Overwrite" in there. I am seeing that nameConflict may not even work with cffile action="write", how could I add maybe just an ascending number to the end of a duplicate file name every time it is generated? The CSV files simply show customer renewal information.
<cfif arguments.isRenewal EQ "Y">
<cffile action="write" file="#filename#" nameconflict="overwrite" output='"Capital","#custName#","","#getCustomer.fname#","#getCustomer.lname#","#getCustomer.serviceAddress1#","#getCustomer.serviceAddress2#","#getCustomer.serviceCity#","#getCustomer.serviceState#","#getCustomer.serviceZip#","#cleanPhone#","#cleanMobilePhone#","#getCustomer.email#","#getCustomer.billingAddress1#","#getCustomer.billingAddress2#","#getCustomer.billingCity#","#getCustomer.billingState#","#getCustomer.billingZip#","0","N/A","Electric","#getCustomer.sdi#","#getCustomer.sdi#","#getProvider.utilityCode#","#getOffer.rateSchedule#","#getOffer.productCode#","#getOffer.rate/100#","kWh","$","#getOffer.rackRateName#","#DateFormat(now(), "yyyy-mm-dd")#","#startDate#","#getOffer.term#","Internet","","","","","","","","","","","","","M2M","#getOffer.evergreenProduct#","Y"'>
<cfelse>
<cffile action="write" file="#filename#" nameconflict="overwrite" output='"Capital","#custName#","","#getCustomer.fname#","#getCustomer.lname#","#getCustomer.serviceAddress1#","#getCustomer.serviceAddress2#","#getCustomer.serviceCity#","#getCustomer.serviceState#","#getCustomer.serviceZip#","#cleanPhone#","#cleanMobilePhone#","#getCustomer.email#","#getCustomer.billingAddress1#","#getCustomer.billingAddress2#","#getCustomer.billingCity#","#getCustomer.billingState#","#getCustomer.billingZip#","0","N/A","Electric","#getCustomer.sdi#","#getCustomer.sdi#","#getProvider.utilityCode#","#getOffer.rateSchedule#","#getOffer.productCode#","#getOffer.rate/100#","kWh","$","#getOffer.rackRateName#","#DateFormat(now(), "yyyy-mm-dd")#","#startDate#","#getOffer.term#","Internet","","","","","","","","","","","","","M2M","#getOffer.evergreenProduct#","N"'>
duplicates snapshot
Is there a way to exclude certain items by filetype in a list in Coldfusion?
Background: I just integrated a compression tool into an existing application and ran into the problem of the person's prior code would automatically grab the file from the upload destination on the server and push it to the Network Attached Storage. The aim now is to stop their NAS migration code from moving all files to the NAS, only those which are not PDF's. What I want to do is loop through their variable that stores the names of the files uploaded, and exclude the pdf's from the list then pass the list onto the NAS code, so all non pdf's are moved and all pdf's uploaded remain on the server. Working with their code is a challenge as no one commented or documented anything and I've been trying several approaches.
<cffile action="upload" destination= "c:\uploads\" result="myfiles" nameconflict="makeunique" >
<cfset fileSys = CreateObject('component','cfc.FileManagement')>
<cfif Len(get.realec_transactionid)>
<cfset internalOnly=1 >
</cfif>
**This line below is what I want to loop through and exclude file names
with pdf extensions **
<cfset uploadedfilenames='#myfiles.clientFile#' >
<CFSET a_insert_time = #TimeFormat(Now(), "HH:mm:ss")#>
<CFSET a_insert_date = #DateFormat(Now(), "mm-dd-yyyy")#>
**This line calls their method from another cfc that has all the file
migration methods.**
<cfset new_file_name = #fileSys.MoveFromUploads(uploadedfilenames)#>
**Once it moves the file to the NAS, it inserts the file info into the
DB table here**
<cfquery name="addFile" datasource="#request.dsn#">
INSERT INTO upload_many (title_id, fileDate, filetime, fileupload)
VALUES('#get.title_id#', '#dateTimeStamp#', '#a_insert_time#', '#new_file_name#')
</cfquery>
<cfelse>
<cffile action="upload" destination= #ExpandPath("./uploaded_files/zip.txt")# nameconflict="overwrite" >
</cfif>
Update 6/18
Trying the recommended code helps with the issue of sorting out filetypes when tested outside of the application, but anytime its integrated into the application to operate on the variable uploadedfilenames the rest of the application fails and the multi-file upload module just throws a status 500 error and no errors are reported in the CF logs. I've found that simply trying to run a cfloop on another variable not related to anything in the code still causes it to error.
As per my understanding, you want to filter-out file names with a specific file type/extension (ex: pdf) from the main list uploadedfilenames. This is one of the easiest ways:
<cfset lFileNames = "C:\myfiles\proj\icon-img-12.png,C:\myfiles\proj\sample-file.ppt,C:\myfiles\proj\fin-doc1.docx,C:\myfiles\proj\fin-doc2.pdf,C:\myfiles\proj\invoice-temp.docx,C:\myfiles\proj\invoice-final.pdf" />
<cfset lResultList = "" />
<cfset fileExtToExclude = "pdf" />
<cfloop list="#lFileNames#" index="fileItem" delimiters=",">
<cfif ListLast(ListLast(fileItem,'\'),'.') NEQ fileExtToExclude>
<cfset lResultList = ListAppend(lResultList,"#fileItem#") />
</cfif>
</cfloop>
Using only List Function provided by ColdFusion this is easily done, you can test and try the code here. I would recommend you to wrap this code around a function for easy handling. Another way to do it would be to use some complex regular expression on the list (if you're looking for a more general solution, outside the context of ColdFusion).
Now, applying the solution to your problem:
<cfset uploadedfilenames='#myfiles.clientFile#' >
<cfset lResultList = "" />
<cfset fileExtToExclude = "pdf" />
<cfloop list="#uploadedfilenames#" index="fileItem" delimiters=",">
<cfif ListLast(ListLast(fileItem,'\'),'.') NEQ fileExtToExclude>
<cfset lResultList = ListAppend(lResultList,fileItem) />
</cfif>
</cfloop>
<cfset uploadedfilenames = lResultList />
<!--- rest of your code continues --->
The result list lResultList is copied to the original variable uploadedfilenames.
I hope I'm not misunderstanding the question, but why don't you just wrap all of that in an if-statement that reads the full file name? Whether the files are coming one by one or through a delimited list, it should be easy to work around.
<cfif !listContains(ListName, '.pdf')>
OR
<cfif FileName does not contain '.pdf'>
then
all the code you posted
I am finishing creating a file upload utility for our site, and if the upload is an invalid format (per our specs not worth going over here) I would want to delete the folder the zip file was unzipped to, and all it's contents.
So far I have used a method of creating a dynamic batch file like this:
<!--- check if folder exists before starting to delete --->
<cfif directoryexists("#file_path_course#")>
<!--- this can be passed in a varaible or whatever --->
<cfset tDirectory = "#file_path_course#">
<!--- This is what we will put in the bat file --->
<cfset tString ="RMDIR /S /Q " & tDirectory>
<!--- generate a .BAT file for later execution --->
<cffile action="WRITE" file="#file_path_course#\delete.bat" output="#tString#">
<!--- Now execute the file to delete everything (Folder and all sub-folders and files)--->
<cfexecute name="#file_path_course#\delete.bat" timeout="60"></cfexecute>
<!--- check if bat file exists --->
<cfif fileexists("#file_path_course#\delete.bat")>
<!--- now delete the bat file --->
<cffile action="DELETE" file="#file_path_course#\delete.bat">
</cfif>
<!--- delete course folder --->
<cfdirectory action="delete" directory="#file_path_course#" recurse="yes">
<cfset course_files_deleted = "Yes">
</cfif>
But I am admittedly concerned about the allowed usage of the cfexecute tag.
There is another option, which uses the cfdirectory recurse delete option, which will do all I ask, but I want to be very sure it's not going to delete the folders/files outside the folder I point it to.
There is a 3rd way, which involves a cfdirectory and looping around it, but I also like the idea of using less lines of code to do a simple operation.
Which option do you trust the most?
I am running IIS7, Coldfusion 8.
Why not just use cfdirectory? You said you were worried that it would delete stuff "outside" the folder you specified. It won't. Simple as that. If it did, then the tag would be broken. :)
Instead of writing a batch file and then executing it, I let ColdFusion do all the work.
<cfset targetDirectory = "C:\Websites\site\thisFolder" />
<cfif directoryExists(targetDirectory)>
<cfdirectory action="list" directory="#targetDirectory#" listInfo="" name="theseFiles" recurse="true" type="file" />
<cfif theseFiles.recordcount gt 0>
<cfloop query="theseFiles">
<cffile action="delete" file="#targetDirectory#/#theseFiles.name#" />
</cfloop>
</cfif>
<cfdirectory action="delete" directory="#uploadDirectory#/#allFolders.name#" />
</cfif>
what i would do is upload the file to a temp directory outside of the webroot. you can use gettempdirectory() to accomplish this which uses your system's temp directory (c:\windows\temp for windows)
then you can unzip the file into a subdirectory off of the temp directory and perform some security checks against the unzipped files and make sure everything is ok, all the while not opening up your site to any attacks. if everything pans out, you can then move the files to their final resting place. if not, just use cfdirectory (as cfjedimaster pointed out) to remove the subdirectory and all the files.