Ask a Jedi: Display value of file upload field

Jay (my second US gov emailer today) asks:

I have not done much with this so I am not sure of the best approach currently I am working on a cf7 server and I am uploading files with some code.

My users would like to be able to see the file name they chose below the upload field since the field is not long enough to display all of it at once.

My initial response was no - since I know the browser locks down those form file fields. But then I remembered that JavaScript should be able to read the setting. Sure enough, it can:

<cfform name="foo"> <cfinput type="file" name="fileone"> <cfdiv bind="{fileone}"> </cfform>

Of course, he asked for a CF7 version. Here is a slightly more verbose version that should work in CF7 (or anything really, even languages on their dead bed).

<script> function setFilename() { var filefield = fileone.value; var output = document.getElementById('filename'); output.innerHTML = filefield; } </script>

<cfform name="foo2"> <cfinput type="file" name="fileone" onChange="setFilename()"> <div id="filename"></div> </cfform>

Archived Comments

Comment 1 by Ben Nadel posted on 9/1/2007 at 12:45 AM

Cool tip. My only comment would be to display Just the file name, rather than the whole path... if you are anything like me, you have about a 10 nested folders and have HUGE paths.

var arrPath = filefield.split( new RegExp( "[\\\/]+", "g" ) )[ 0 ];

output.innerHTML = arrPath[ arrPath.length - 1 ];

Thats not tested, but it should break the Path by path delimiter and then use the last item (the actual file name).

Just my 2 cents. Of course, I do have horrible directory structures.

Comment 2 by todd sharp posted on 9/1/2007 at 12:47 AM

How bout just showing the filename, not the whole path?

<script>
function setFilename() {

var filefield = document.getElementById('fileone').value;
var output = document.getElementById('filename');
var sep = '\\'

//check for '/' file seperator
if(filefield.indexOf('/') >= 0){
sep = '/';
}

var fileNameArr = filefield.split(sep);

output.innerHTML = fileNameArr[fileNameArr.length-1];
}
</script>

Comment 3 by todd sharp posted on 9/1/2007 at 12:48 AM

Wow, I hadn't seen your comment first there Ben! Great minds think alike ;)

Comment 4 by Ben Nadel posted on 9/1/2007 at 12:50 AM

Ha ha, that's funny. Yeah, we were probably typing at the same time. Sure beats the heck out of concentrating on my own work at 4:50 PM on a Friday afternoon :) ... Day almost over!

Comment 5 by Raymond Camden posted on 9/1/2007 at 12:51 AM

That is a perfect idea.

I'm going to see if I can do a cf8 version.

Comment 6 by Raymond Camden posted on 9/1/2007 at 12:58 AM

Ben, I couldn't get your JS to work. Anyway, here is a CF8 version and man, that was a good idea you guys.

<script>
getFilename = function() {
var filefield = fileone.value;
var sep = '\\'

//check for '/' file seperator
if(filefield.indexOf('/') >= 0) sep = '/';
var fileNameArr = filefield.split(sep);

return fileNameArr[fileNameArr.length-1];
}
</script>

<cfform name="foo">
<cfinput type="file" name="fileone">
<cfdiv bind="javascript:getFilename({fileone})">
</cfform>

Comment 7 by Ben Nadel posted on 9/1/2007 at 1:03 AM

No worries - I didn't test mine. That's cool that you can bind right to a JS function!

Comment 8 by todd sharp posted on 9/1/2007 at 1:04 AM

Careful with the first line (declaring filefield) - IE doesn't like the fileone.value... Change it to var filefield = document.getElementById('fileone').value; and IE is happy too... But I like that CF8 version - man is that easy...

Comment 9 by Raymond Camden posted on 9/1/2007 at 1:07 AM

Oh yeah - I normally do to the getElementCrap - I was just being lazy. I wish CF would auto drop a shortcut like spry does:

var somefield = Spry.$("id")

Ben: Yep, there are 3 main binds - and each have their own rules about when you can use them. The JS one here is nice. It lets me kind of filter things out. You could actually have 2 (or more) fields that did a bind like so:

field1 bind: javascript:someFunc({a})
field2 bind: javascript:someFunc({b})

Notice that they use the same JS funcs, but different values for binding.

This could be useful if, for example, cfgrid data wasn't formatted like you want.