Copy link to clipboard
Copied
I am having trouble uploading files after migrating the site from local environment to the web. Following is the relevant section of code from a coldfusion function that uploads files using BlueImp:
<cffunction name="POST" access="private" returnformat="json">
<cfargument name="options" type="struct" required="true">
<cfargument name="listing_id" type="any" required="false" default="">
<cfset var result = 0 >
<cfset var vThumbnail = 0 >
<cfset var fileInfo = "" >
<cfset var fileName = "" >
<cftry>
<cfset fileInfo = GetFileInfo(form['files[]']) />
<!---<cfdump var="#fileInfo#"><cfabort>--->
...
In my local environment, selecting a file produces the following, which is a dump of the form variables used by the function:
LOCAL DEV ENVIRONMENT
Then BlueImp does its thing via the POST function shown above and the <cfdump var="#fileInfo#"> in the above code returns something like the following:
LOCAL DEV ENVIRONMENT
But, after uploading the site to Hostek, the initial file selection produces a similar form variables dump to the local environment, i.e.
REMOTE (LIVE) ENVIRONMENT:
BUT, the <cfdump var="#fileInfo#"> just returns zero (0) in the network tab. There is no dump structure as with the local environment.
Any ideas what could be going on?
2 Correct answers
Yes, it is indeed a permissions thing. That is the cause of the issue right there. Apparently, the Tomcat application server is preventing Javascript from gaining direct access to one of its files. Which is a very good thing! 🙂
Why the error occurs on ColdFusion 2023 but not on ColdFusion 11? ColdFusion's security gets progressively tighter as you upgrade. So ColdFusion 2023 has more bouncers at the door than ColdFusion 11.
The challenge now is to find a solution to this "access" problem.
Thanks for the update. Very interesting test result indeed!
It confirms my new hypothesis that ColdFusion, in general, and CFCs, in particular, are not necessarily denied access to Tomcat's tmp directory. Rather, it is the call getFileInfo() that is being denied permission.
Has getFileInfo() been denied read/write permissions in the sandbox, perhaps? I think it's a good idea to ask the server administrator.
Out of curiosity, did you, for the sake of rigour, use this code:
fileopen(form['fi
...
Copy link to clipboard
Copied
Hi guys,
I'm only just catching up with your replies and many thanks for persisting with me through this.
Before I saw your latest replies, I did some testing using Charlie's idea of just simplifying it as a starting point:
upload.cfm
<form method="post" name="post-form" enctype="multipart/form-data" action="upload_action.cfm">
<input type="File" name="test"><br>
<input type="Submit"><br>
</form>
upload_action cfm
Here I just used a url that the code had failed on with the BlueImp process at GetFIleInfo()
<cffile
action = "upload"
destination = "C:\ColdFusion2023\cfusion\runtime\work\Catalina\localhost\tmp\neotmp14670862617474925576.tmp"
fileField = "test"
nameConflict = "overwrite"
result = "res"
Errors = "resErrors">
<cfdump var="#res#">
res dump
So, it seems it did write to the location.
Yes GetFileInfo() in the BlueImp code says it can't, or didn't, or something.
access denied (&quot;java.io.FilePermission&quot; &quot;C:\ColdFusion2023\cfusion\runtime\work\Catalina\localhost\tmp\neotmp14670862617474925576.tmp&quot; &quot;write&quot;)
I have a day job and have to get going, but will read your reponses when I get back.
Copy link to clipboard
Copied
As I have explained, upload is NOT the problem. The problem is the CFC's attempt to read a file within Tomcat by means of
<!---
form['files[]'] is the full path of a file within Tomcat.
That is, C:\ColdFusion2023\cfusion\runtime\work\Catalina\localhost\tmp\neotmp14670862617474925576.tmp.
"Access Denied" indicates that Upload.cfc is not allowed to read the file.
--->
<cfset fileInfo = GetFileInfo(form['files[]']) />
In fact, the explanation I've mentioned comes with a fully worked out code example. I wrote the code in such a way as to enable you to copy-paste it in your application. 🙂
Copy link to clipboard
Copied
Paul good to see you try the cffile action="upload". Unfortunately, you somehow misread the docs. The destination should NOT be that temp folder. (Instead that folder is where the file gets uploaded by cf when a file is sent with a form post to a cf page. I explain that more in my blog post.)
Instead, the destination attribute should name where you want the file to end up (which must be a destination that Cf has permission to write to) .
Then you can do with it what you want. BTW, the cffile variable will hold all the info you seek, like what was the file name as uploaded, its mime type, and much more.
/Charlie (troubleshooter, carehart. org)
Copy link to clipboard
Copied
BKBK, I tried your suggestion and I get the error:
Element CLIENTFILE is undefined in CFFILE. |
Copy link to clipboard
Copied
BKBK, I tried your suggestion and I get the error:
Element CLIENTFILE is undefined in CFFILE.
By paul_8809
The error suggests that ColdFusion couldn't find the uploaded file. Anyway, this motivated me to create a fuller test=case, based closely on your code.
Here it is. Both the CFM and CFC are assumed to be in the same directory. If they aren't, then use the appropriate relative path for the form's action.
Upload.cfc
<cfcomponent>
<cffunction name="init" access="remote" returnformat="json">
<cfscript>
var options = {
"uploadPath" : "",
"uploadURL" : "",
"maxFileSize" : 1 * 1024 * 1024,
"okExtensions" : "jpg,jpeg,gif,png",
"watermark": {
"enabled" : true,
"watermarkPath" : "watermark/watermark.png",
"watermarkPossX": "right",
"watermarkPossY": "bottom",
"transparency" : 50
},
"thumbnails":
{
"enabled" : false,
"width" : "100",
"height" : "100",
"uploadPath": "",
"uploadURL" : "",
"interpolation" : "highestQuality"
}
}
if (GetHttpRequestData().method == "GET")
{
if (structKeyExists(url,"file") && url.file != "")
return DELETE(options);
}
else if (GetHttpRequestData().method EQ "POST")
{
return POST(options);
}
</cfscript>
</cffunction>
<cffunction name="POST" >
<!--- Other stuff --->
<!--- Define full path to a directory for uploads. Define any, as long as ColdFusion has access to it --->
<cfset CFDirForUploadedFiles = expandpath('.')>
<cftry>
<!--- ColdFusion uploads file to a directory of your choice--->
<!--- Requirement for the upload: the uploading form must have multipart/form-data attribute.
That is, <form enctype="multipart/form-data"> --->
<cffile action = "upload"
fileField = "files[]"
destination="#CFDirForUploadedFiles#"
nameConflict = "overwrite">
<!--- If upload succeeds, ColdFusion will automatically create the 'cffile' structure --->
<cfset filepath = CFDirForUploadedFiles & "/" & cffile.clientfile>
<cfset fileInfo = GetFileInfo(filepath)>
<p>
<!--- Debugging code: Dump cffile to see the properties of the upload --->
<cfdump var="#cffile#" label="Properties of the upload">
<p>
<cfdump var="#fileInfo#" label="FileInfo">
<cfcatch type="any">
<cfdump var="#cfcatch#">
</cfcatch>
</cftry>
<!--- Other stuff --->
</cffunction>
</cfcomponent>
uploadIt.cfm
<form action="Upload.cfc?method=init" method="post" enctype="multipart/form-data">
<input name="files[]" type="file" id="fileupload">
<input type="submit" name="sbmt" value="Submit">
</form>
Copy link to clipboard
Copied
BKBK, unless I'm missing something, which I probably am, the code you provided is essentially what I currently have, and it fails at
<cfset var filepath = CFDirForUploadedFiles & "/" & cffile.clientfile>
resulting in the afore-mentioned error, which as you suggested, means it couldn't fint the uploaded file.
FYI, a guy from Hostek says "The security sandbox does have the path listed and allows read access to \catalina\localhost\temp."
Below is the cfc I currently have:
upload.cfc
<cffunction name="init" access="remote" returnformat="json">
<cfscript>
var options =
"uploadPath" : "files/uploads",
"uploadURL" : "/js/jQuery-File-Upload-master/server/cf/files/uploads",
"maxFileSize" : 1 * 1024 * 1024,
"okExtensions" : "jpg,jpeg,gif,png",
"watermark":
{
"enabled" : true,
"watermarkPath" : "watermark/watermark.png",
"watermarkPossX": "right", //left,right or number
"watermarkPossY": "bottom", //top,bottom or number
"transparency" : 50 //top,bottom or number
},
"thumbnails":
{
"enabled" : false,
"width" : "100",
"height" : "100",
"uploadPath" : "files/uploads/thumbs",
"uploadURL" : "/js/jQuery-File-Upload-master/server/cf/files/uploads/thumbs",
"interpolation" : "highestQuality",
"quality" : 1,
"watermark":
{
"enabled" : false,
"watermarkPath" : "watermark/watermarkSmall.png",
"watermarkPossX": "right", //left,right or number
"watermarkPossY": "bottom", //top,bottom or number
"transparency" : 50 //top,bottom or number
}
}
};
if (GetHttpRequestData().method == "GET"){
if (structKeyExists(url,"file") && url.file != "")
return DELETE(options);
}
else if (GetHttpRequestData().method EQ "POST")
{
return POST(options);
}
</cfscript>
</cffunction>
<cffunction name="POST" access="private" returnformat="json">
<cfargument name="options" type="struct" required="true">
<cfargument name="listing_id" type="any" required="false" default="">
<cfset var result = 0 >
<cfset var vThumbnail = 0 >
<cfset var fileInfo = "" >
<cfset var fileName = "" >
<!--- <cfset fileInfo = GetFileInfo(form['files[]']) /> Error occurred here --->
<cfset fileName = Lcase(getClientFileName('files[]'))>
<!--- following commented out because it relied on getFileInfo --->
<!---<cfif fileInfo.size gt options.maxFileSize or not listfind(application.friendly_accepted_extensions,ListLast(fileName,"."))>
<cfif fileInfo.size gt options.maxFileSize>
<cfreturn SerializeJSON(
{"files":
[{
"name": "#fileName#",
"size": "#fileInfo.size#",
"error": "File is too large"
}]
}
)>
</cfif>
<cfif not listfind(application.friendly_accepted_extensions,ListLast(fileName,"."))>
<cfreturn SerializeJSON(
{"files":
[{
"name": "#fileName#",
"size": "#fileInfo.size#",
"error": "Only #application.friendly_accepted_extensions# files are accepted"
}]
}
)>
</cfif>
<cfelse>--->
<!--- end of commenting out section requiring getFileInfo() --->
<!--- Upload the file --->
<cfset var CFDirForUploadedFiles = expandpath(options.uploadPath)>
<cftry>
<cffile action="upload" fileField="files[]" destination="#CFDirForUploadedFiles#" nameConflict="makeUnique" result="upload">
<cfset var filepath = CFDirForUploadedFiles & "/" & cffile.clientfile>
<cfset var fileInfo = GetFileInfo(filepath)>
<!---<cfdump var="#fileInfo#"><cfabort>---> <!--- this produced error "Element CLIENTFILE is undefined in CFFILE.--->
<cfcatch type="any">
<cfdump var="#cfcatch#"><cfabort>
</cfcatch>
</cftry>
...
</cffunction>
form
<form id="fileupload" action="//jquery-file-upload.appspot.com/" method="POST" enctype="multipart/form-data">
...etc...
I haven't investigated the action attribute, but I assume it still works as we already know the file does write to the server. The error seems to be in reading the file back. Theoretically, if the Hostek guy says we have read access, there shouldn't be a problem.
Copy link to clipboard
Copied
Paul, I honestly think you'll save yourself time and frustration to abandon having us focus on all that code. Instead, create a simple several line template to do a prompt to upload a file, then (in the same or another template) do cffile action="upload", and dump the cffile scope.
Does that work? That will tell you if there some issue on that server that somehow preclude uploads. It may not. In that case, then you can figure what differs with your real code.
/Charlie (troubleshooter, carehart. org)
Copy link to clipboard
Copied
Sure, I just wanted BKBK to see exactly what was in my code to save himself time generating what I already have.
Copy link to clipboard
Copied
@paul_8809 , you have actually not copy-pasted my code as I suggested. Anyway, you're almost there.
I think you get the error because you introduced the attribute "result". That attribute is mutually exclusive to "cffile".
So delete
result="upload"
Copy link to clipboard
Copied
Alternatively, if you insist on using the "result" attribute:
<cffile action="upload" fileField="files[]" destination="#CFDirForUploadedFiles#" nameConflict="makeUnique" result="upload">
<cfset var filepath = CFDirForUploadedFiles & "/" & upload.clientfile>
<!--- Debugging code: Dump cffile to see the properties of the upload --->
<cfdump var="#upload#" label="Properties of the upload">
Copy link to clipboard
Copied
Yes, that change gets me a nice dump:
But I still have to figure out why the getFileInfo() code, prior to upload, fails. Everything works apart from that. If I comment that section out, as per my last post, I get files uploading as normal, albeit without any checks on size and extension.
Copy link to clipboard
Copied
upload.cfm
<form method="post" name="post-form" enctype="multipart/form-data" action="upload_action.cfm">
<input type="File" name="test">
<input type="Submit">
</form>
upload_action.cfm
<cfset fileInfo = GetFileInfo(form.test) />
<cfdump var="#fileInfo#">
Produces the permissions error:
access denied ("java.io.FilePermission" "C:\ColdFusion2023\cfusion\runtime\work\Catalina\localhost\tmp\neotmp13287764199720674387.tmp
Copy link to clipboard
Copied
Paul, why do you keep trying to look at that temp file? And you're not even doing the cffile action="upload" in that example? Why not? Especially when things worked in the previous example output you showed (that DID do that)?
It seems you feel some compelling motivation to grab that file. It's not for you to do: it's for that cffile upload action to do. I explained this in the first reply, last week, 36 replies ago, and with more detail in the blog post I pointed to then. Have you had a moment to read it? It could help you.
Otherwise, why are you insisting on touching that temp file? What's your motivation? This has gone on too long, so it's time to get this clarification--on your end or ours.
/Charlie (troubleshooter, carehart. org)
Copy link to clipboard
Copied
Is it not the case that when you select a file, it stores it in that temp location? If so, I should be able to read it and perform checks related to file size and acceptable extensions prior to sending it to its ultimate destination.
Copy link to clipboard
Copied
Hi @paul_8809 , That's an interesting question. ColdFusion's designers had actually anticipated it, and provided an answer: the cffile struct or, alternatively, the result struct.
Take another look at your last printscreen. You will see that the struct contains keys such as filesize, clientFileExt, contentType and more besides.
However, the question remains why the call getFileInfo(filepath_in_Tomcat_tmp_directory) results in ("access denied", "java.io.FilePermission"). Yes, access is denied and, yes, it's a permissions issue. But from what you've shown us so far, the permissions that have been denied have been "read" or "write".
That gets me wondering now whether this is really about Tomcat's security against ColdFusion. What if it instead has to do with concurrency. By this I mean, for example, a situation whereby one thread tries to read a file while a second thread is still busy writing to it. What if "Access Denied" is just a means of preventing such a race condition?
One way to test this hypotheses is by using a lock. Try the following in your test, and see what happens:
upload_action.cfm
<cflock name = "uploadLock" type = "readonly" timeout = "60" throwOnTimeout = "yes">
<cfset fileInfo = GetFileInfo(form.test) />
<cfdump var="#fileInfo#">
</cflock>
Copy link to clipboard
Copied
I tried it and get the same error. Should the cflock encompass more of the code, like right from the <form>?
It's perplexing. fileExists() returns "yes", I can do a readbinary on it. Just can't do getFileInfo(). I've sent my simple example to Hostek. Maybe they can explain it.
Copy link to clipboard
Copied
Aha, just found out I can use fileOpen() in a similar way. This seems to get me what I want:
Gotcha!
Copy link to clipboard
Copied
Thanks for the update. Very interesting test result indeed!
It confirms my new hypothesis that ColdFusion, in general, and CFCs, in particular, are not necessarily denied access to Tomcat's tmp directory. Rather, it is the call getFileInfo() that is being denied permission.
Has getFileInfo() been denied read/write permissions in the sandbox, perhaps? I think it's a good idea to ask the server administrator.
Out of curiosity, did you, for the sake of rigour, use this code:
fileopen(form['files[]'])
Should the cflock encompass more of the code, like right from the <form>?
By paul_8809
Good question. As answer, here is a suggestion:
upload.cfm
<cflock name = "uploadLock123" type = "exclusive" timeout = "60" throwOnTimeout = "yes">
<form method="post" name="post-form" enctype="multipart/form-data" action="upload_action.cfm">
<input type="File" name="test">
<input type="Submit">
</form>
</cflock>
upload_action.cfm
<cflock name = "uploadLock123" type = "readonly" timeout = "60" throwOnTimeout = "yes">
<cfset fileInfo = GetFileInfo(form.test) />
<cfdump var="#fileInfo#">
</cflock>
Copy link to clipboard
Copied
Got it with the cflock. Was wondering how to accomplish that over the span of two templates.
Yes, I used
fileopen(form['files[]'])
Everything is working now. And yes, I've asked the server admin. They're slow to reply. Thanls for your help and patience.
Copy link to clipboard
Copied
No worries.


-
- 1
- 2