Uploaded filename, before CFFile

Guest
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

Hi,

I'm doing some form data validation and would like to add rules for files (size and type). Ideally I want to avoid CFFile as the validation shouldn't have anything to do with moving the file anywhere.

I know that when ColdFusion processes an upload, it stores it in a temporary directory and filename. This is stored in the form field (e.g. form.file = c:\sometempdirectory\blahxxx.tmp) and I can use that to do a GetFileInfo and find out the filesize. Awesome.... except it's called blahxxx.tmp :(

I want to know the real filename, not the temp filename but I can't find it anywhere. ColdFusion must know it, probably hidden along with its other darkest secrets, as it'll use it when we do a CFFile action="upload". So where is it being hidden? Any ideas?

I have seen suggestions of using an extra hidden field plus some javascript, but to be honest, I don't like trusting something like that as it's possible to abuse it. I've also gone hunting inside "getPageContext().getRequest()" but not being any good with Java I haven't a clue where to start.

Please help :)
Ta,
Dave
TOPICS
Advanced techniques

Views

5.8K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

look at #cffile.clientFile# I would start by doing a <cfdump var="#FILE#"> and <cfdump var="#CFFILE#"> Then you can look at all the properties of the two structs and decide what you are actually looking for. CFDump and CFAbort are two of your best friends when you start moving into new waters....

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

Thanks for the reply Bob, but I think you may have missed what I'm trying to do.

I'll summarise it for everyone...

Form.cfm

* Form page has a file field
* User selects the file "rincewind.txt" and clicks submit.
* Form action points at save.cfm

Save.cfm
* Validation.cfc created and given rules.
* Validates file size by using GetFileInfo(form.file).
* Tries to validate file type but form.file ends in .tmp not .txt

My problem is I want the real filename. There is no CFFile action="upload" in save.cfm so the file / cffile variables do not exist. All I'm currently doing is validation and I don't want my validation component moving files about the place as I'd then have the extra work of cleaning up if they're invalid and letting everything else know it's new location.

My theory is ColdFusion must hold the original filename somewhere before the CFFile since it'll rename and move the file. CFFile action="upload" can be misleading too, as the file has already been uploaded and stored in a temporary directory by ColdFusion (check out the form variable next time you do an upload), but (oh woe is me) with a tmp extension so I can't validate it. 😞

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

elpestybandito wrote:
> My theory is ColdFusion must hold the original filename somewhere
> before the CFFile since it'll rename and move the file. CFFile
> action="upload" can be misleading too, as the file has already been uploaded
> and stored in a temporary directory by ColdFusion (check out the form variable
> next time you do an upload), but (oh woe is me) with a tmp extension so I can't
> validate it. :(
>
>

You do understand the HTTP request/response client/server scenario (many
people who post questions like this do not). Try investigating the CGI
scope and the request header/body. I would suspect the file name is
buried in one or more of those locations. I don't recall off the top of
my head how one inspects the request head and body, but I suspect Google
would quickly cough up examples.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Azadi, please try to remain civil and read through everything in the post so far before responding.

Looking at your comment you seemed to have the impression that I don't know how file uploads work. I can promise you that I do and if you paid closer attention to my comments you would realise that.

To quote myself "there seems to be some confusion that the upload doesn't happen until you do cffile action="upload". This is not the case and I'll show this here." Doesn't that say that cffile action="upload" isn't responsible for the upload itself?

You pointed me to Ian's comment, how about you read his second comment (that he probably made once he read through my post again and realised I know what's going on).

quote:

Originally posted by: Ian Skinner
You do understand the HTTP request/response client/server scenario (many
people who post questions like this do not). Try investigating the CGI
scope and the request header/body. I would suspect the file name is
buried in one or more of those locations. I don't recall off the top of
my head how one inspects the request head and body, but I suspect Google
would quickly cough up examples.



How about a little list to make things clearer.

* I know CFFile action="upload" is not doing the upload
* I know the server handles the upload and CF stores the file before running the ColdFusion code.
* I know that form.file holds the temporary location and filename of the upload.
* I don't want a client-side method for finding the original name, I prefer server-side for this.
* I do want to know where ColdFusion stores the original filenames of uploads.
* I don't want to use CFFile action="upload" to get at the original filenames.

If you look through that list and my previous comments things should make more sense. I've searched the GetPathContext() function and it's methods but I'm not really sure where to look within it. I've also searched the CGI scope (and it's keys that don't show up in a CFDump) and I've even looked in GetHttpRequestData() but this doesn't return anything in CF8 when there is an upload (to increase performance for large file uploads).

What I do know is that ColdFusion is storing this filename somewhere, because it makes use of it when you ask it to.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

my apologies, i didn't fully read your last paragraph in your previous
post...

so you probably also know that the original file name is sent with the
http request in the headers?

a simple header sniffing returns something like this after form submit:

Content-Disposition: form-data; name="fileupload"; filename="bg_mfa.png"


i do not, however, know how to get that data on the server side...

Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

elpestybandito wrote:
> I haven't a clue where to start.
>
> Please help :)

Start by understanding the HTTP request/response client/server process.

1) A user viewing a form in a browser selects a file to be uploaded and
submits the form. The browser reads the file from the user's system and
puts it into the request which then it sends to the web server.

2) The web server receives the request, takes the file from the request
and writes it to a temporary location on the server. It then passes the
request on to ColdFusion telling it where the temporary file is located.

3) ColdFusion then does what you request it to do with the file
according the the <cffile...> and other CFML instructions.

Understanding this process you can see what you ask is impossible and
does not make sense. You can not process the file name on the server
before the file is sent because the browser does not send this
information ahead of the file it sends the entire file, name and all,
when the form action request is made.

Your interceptions points are on the client, which requires some kind of
client side technology such as JavaScript.

In the web server. Some of which offer some type of scripting
capabilities that may do what you want.

In the Application Sever, i.e. ColdFusion. This is the easiest and best
practice and should always be done. Even if you do a client side option
, such as JavaScript, you will want to back it up with a Server Side
solution for just the reason you mentioned. Client side code and be
messed with and circumvented.


Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

Thanks, I've tried hunting through the CGI scope but using ColdFusion 8 the request body (usually used for the post variables) is always empty. This is due to a setting to stop extremely large uploads from being held in memory.

I had thought about hunting through the getPageContext().getRequest() or other areas in that function but since finding out that the contents isn't held I guess it wouldn't be stored in there either.

I just feel like there's an extra step that's involved for little reason with file uploads in ColdFusion that could be avoided if there was some access to the original filename.

For exampe:
* Validating the file extension, as you'd want to know it's a valid file before moving it.
* Uploading files to the database. You can do a <cffile action="readbinary" file="#form.file#" variable="blob" /> to get the uploaded file (without bothering with action="upload" at all) and store it in a database. One less step but currently you lose the original filename.

I guess that unless someone knows where the real filename is hidden I'll be all out of luck.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

The following script will capture the user's full path to the file in a hidden field. From there, you can extract out the filename on the form submission before you process the cffile.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

Thanks c_wigginton, but my plan was to avoid anything client side. Since I didn't want someone to come along, disable JavaScript and enter something in the hidden field that's different from the existing field.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

I went down your same path awhile ago and couldn't find any alternatives other than client side when using CFFILE. CFFILE prior to CF8 is also memory intensive. You can look at is using something other than CF for the file upload. I've used JavaZoom's upload bean which uses JSP's and POJO's for the upload and works with JRun. The UploadBean provides the ability to obtain the uploaded file name.

http://www.javazoom.net/jzservlets/uploadbean/documentation/developerguide.html

Having said that, you really need to ask yourself is why are you completely afraid of client side? The key point is you don't have much control anyways from a client perspective on what is getting uploaded prior to the upload event. You can certainly apply filtering through a CFFILE accept attribute, but you can't guarantee the name of the file or what is in the file.

For example, you can use a simple copy command to combine a gif images with other file types, the below web link references combination with MP3. The uploaded file will still identify as a gif mime type even though there's hidden data in the file.

ref: http://www.raymond.cc/blog/archives/2006/06/26/hide-mp3-audio-inside-gif-picture/

So worrying about someone hacking the uploaded file name in a hidden field is moot since they could simply rename the file anything they wanted before selecting it in the browser.

As far as turning off JavaScript, you can force JavaScript being enabled by having the submit button being disabled and then enable the button when the document is loaded. jQuery is really nice for this.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 05, 2008 Mar 05, 2008

Copy link to clipboard

Copied

Thanks for the info c_wigginton, it's certainly true that there are still ways to get around any restrictions I try and place on the file type but I still like to do as much as I can server-side in the way of validation.

Azadi, thanks for the link, that's not a bad idea about the file checking that way.

In the end I've gone for the following example, I'm using CF8 so it doesn't seem to affect performance from what I can tell. I would be so much easier if I had the original filename another way but I guess this'll have to do.

<!--- Retrieve the file information by making a copy --->
<cffile action="upload" filefield="form.file" nameconflict="makeUnique" result="info" destination="#GetTempDirectory()#" />
<!--- Remove the temp copy --->
<cffile action="delete" file="#GetTempDirectory()#\#info.serverFile#" />

This way any code that wishes to do a CFFile action="upload" will still work and I get to validate the filename. Seems a bit much overhead but unless Adobe give up the secret of where the name is kept... 😉

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 09, 2008 Mar 09, 2008

Copy link to clipboard

Copied

function getFileName(tf, tfn)
{
var f = document.getElementById(tf);
var fv = f.value
var s = fv.lastIndexOf("\\");
var n = fv.substring(s + 1);
document.getElementById(tfn).value = n;
return true;
}

In the above:
tf is the file field on the form
tfn is a hidden field that you save the file name in that you parsed from the file field

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 09, 2008 Mar 09, 2008

Copy link to clipboard

Copied

Oh Yes, call the function with the onsubmit on the form

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Elpestybandito wrote:
I know that when ColdFusion processes an upload, it stores it in a temporary directory and filename. This is stored in the form field (e.g. form.file = c:\sometempdirectory\blahxxx.tmp) and I can use that to do a GetFileInfo and find out the filesize. Awesome.... except it's called blahxxx.tmp 😞

What you've described is not always the case. That is what happens if you don't specify a full path to a directory as the destination attribute, when you upload the file in the first place. (Or if you, for some bizarre reason, specify Coldfusion's system temp directory as the destination).

As an example, create the directory c:\my_uploaded_pics\. When you run the code below, Coldfusion will save the image, including its real name and extension, in your directory. Practically all the information you seek with getFileInfo is contained in the structure cffile.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Thanks everyone for taking the time to check this topic but I've given up on what I was really after. But I will try to explain it as everyone seems to be mis-understanding what actually happens and what I was after.

Firstly, I didn't want to rely on Client-side JavaScript because that's more open to abuse if not checked on the server-side.

Now imagine I have two files. Form.cfm and Save.cfm. Form.cfm contains just the form with a file upload box, this form submits to Save.cfm.

Now for save.cfm, there seems to be some confusion that the upload doesn't happen until you do cffile action="upload". This is not the case and I'll show this here.

Save.cfm

<cfdump var="#form.upload#" />
<!--- Will display the temporary location of the upload
The variable simple contains a string, nothing special
--->
<cfdump var="#GetFileInfo(form.upload)#" />
<!--- Will display file size and other details --->
<cffile action="read" file="#form.upload#" variable="file" />
<!--- File variable now contains the contents of the upload --->
<cfquery name="qInsertDoc" datasource="aDsn">
INSERT INTO tblDocs (upload)
VALUES (
<cfqueryparam cfsqltype="cf_sql_blob" value="#file#" />
)
</cfquery>

Now, please notice I didn't once use CFFile action="upload" but I still get the file and throw it into the database. More importantly the upload has already taken place and finished before save.cfm is executed. The only difference between doing it this way and doing it the cffile action="upload" way is I can't find out the original filename. All I ever wanted to know was where ColdFusion is hiding that name.

The reason I'm after that, without doing a CFFile action="upload", is this because I didn't want my validation component creating a copy of a file (which is all cffile action="upload" does) just to find out it's original name in order to validate it. And remember I don't want to rely on client-side JavaScript as that can be circumvented.

Thanks

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Ian Skinner has already explained to you in his post how and why this
happens.

cffile action="upload" DOES NOT upload the file - it merely moves it
from a temp location where the http request has put it to the folder you
specify in the destination attribute of cffile tag.

the file selected in the form's type='file' field get sent to the server
as part of http request. it is not 'taken' from the user's computer by
some process - it is in the http request sent to the server when you hit
'submit' button.

read Ian's post.

Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Thanks Azadi :)

That's exactly what I'm after, just can't find how to access it from ColdFusion. Like I've mention before, it must be there somewhere otherwise ColdFusion wouldn't be able to use the original filename at all.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 10, 2008 Mar 10, 2008

Copy link to clipboard

Copied

Elpestybandito wrote:
Now for save.cfm, there seems to be some confusion that the upload doesn't happen until you do cffile action="upload".

That is not where the confusion is. It is well-known that you can upload without using <cffile action="upload">.

I can only speak for myself. What confuses me is why you don't just use <cffile action="upload" destination="#absolutePathToDirectoryYouSpecify#">. It will save the file by its real name, which is what you want, and in the directory you specify.

It might just be -- and I'm guessing -- that Coldfusion will only give you the real name when you use <cffile action="upload">. In any case, you will get more bang for your buck with the cffile structure than with GetFileInfo().

Another point of confusion is that you use <cffile action="read">, which applies mainly to text files. What do you do for images and executables, for example? Toggle between action="read" and action="readBinary"? Then what about MIME types? Permissions?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 11, 2008 Mar 11, 2008

Copy link to clipboard

Copied

> That is not where the confusion is. It is well-known that you can upload without using <cffile action="upload">.

I have had several replies here and elsewhere where people have thought CfFile action="upload" is responsible or they think I believe it is responsible. That's why I mentioned there appears to be some confusion, as I have kept having to explain what I wish to accomplish.

> What confuses me is why you don't just use <cffile action="upload" destination="#absolutePathToDirectoryYouSpecify#">

I have built a Validation CFC which is provided a set of multiple rules per form field. I already have it validating the file size (GetFileInfo(form.file)) but I didn't want the overhead of creating a copy of the upload (CfFile action="upload") and then removing it, just to find out it's file type. I also wanted the validation CFC to remain independent from any other code and portable between various applications, doing a CFFile action="upload" means I always have to remember that my validation cfc is copying the file somewhere.

Also, when I want to validation multiple file uploads, some possibly large files. There is the overhead of ColdFusion copying each one of these, just to find it's filename.

> Another point of confusion is that you use <cffile action="read">

The example code was based on some I was using for uploading, changing and then saving an RTF file. So I didn't want to open it as a binary, sorry if it appeared wrong.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 11, 2008 Mar 11, 2008

Copy link to clipboard

Copied

I didn't want the overhead of creating a copy of the upload (CfFile action="upload") and then removing it, just to find out it's file type.

There will always be the overhead of uploading the file to the server. I believe that that has more to do with HTML. It's the expected behaviour for <input type="File">. So, even without <cffile action="upload">, Coldfusion will upload the file to the temporary directory, giving it an arbitrary name like neotmp9381.tmp. That is default behaviour for Coldfusion.

A possible solution to your problem is to pass the client's file path, including file name, using cfinput's bind attribute. An example follows:

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 14, 2019 Jan 14, 2019

Copy link to clipboard

Copied

LATEST

Hello Dave, have you been able to finally find the answer to this?

If someone still needs to get the filename of the uploaded file, please check this out:

Stillnet Studios » Blog Archive » Getting the client filename before using cffile

It works great.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines