views:

463

answers:

4

I have a very simple file upload that allows users to upload PDF files. On another page I then reference those files through an anchor tag. However, it seems that when a user upload a file that contains the pound sign (#) it breaks the anchor tag. It doesn't cause any type of Coldfusion error, it just can't find the file. If I remove the #, it works just fine. I am sure there are a number of other characters that would have this same issue.

I've tried putting URLEncodedFormat() around the file name inside the anchor but that doesn't help. The only other thing I could think of was to rename the file each time it was uploaded and remove the "#" character (and any other "bad" character).

There has got to be an easier solution. Any ideas?

A: 

Pound signs are not legal within filenames on the web. They are used for in-page anchor targets:

<a name="target">

So if you have file#name.pdf, the browser is actually looking for the file "file" and the internal anchor "name.pdf".

Yes, you will have to rename your files on upload.

Ben Doom
I understand that I will have to rename. My question would be what is the easiest solution to take care of the # character as well as any others that might cause issues.
Jason
check out replace() or replaceList()
Henry
@Ben - I could be wrong, but I do not think you "have to" rename. Properly encoding the # sign should work (ie file%23.pdf). But I do agree that renaming is the better option here (especially given CF's sensitivity to #).
Leigh
I ran into this a few years ago. From what I remember, you have to escape the # both on the file and in the link. At least, on an older version of IIS.
Ben Doom
Yes, I think tricky part is "properly" escaping it (in a CF context anyway). But just in case someone really could not rename, I wanted to mention escaping should be an option.
Leigh
Other than pre-processing the file request a la mod-rewrite and its ilk, how would you escape the filename on the file itself without renaming it?
Ben Doom
I do not think you can. What I meant was escaping the # in the url alone _should_ work with most newer web servers. At least afaik. I am not sure about older versions of IIS.
Leigh
+3  A: 

If you control the file upload code try validating the string with

 IsValid("url",usersFileName) or
 IsValid("regex",usersFileName,"[a-zA-Z0-9]")

Otherwise if you are comfortable with regex I would suggest something like the previous posters are commenting on

  REReplace(usersfilename,"[^a-zA-Z0-9]","","ALL")

These samples assume you will add the ".pdf" and only allows letters and numbers. If you need underscores or the period it would look like this...

  REReplace(usersfilename,"[^a-zA-Z0-9\._]","","ALL")

I am not a regex guru, if I have one of these wrong I am sure several will jump in and correct me :)

kevink
Yes, we do something similar to the latter expression. But replace the removed characters with something like "_" to make it obvious the file name was altered. Strictly personal preference though :)
Leigh
This is a pretty good approach. Wish I'd thought of it.
Ben Doom
This is more or less what I do. Like Leigh, I replace all substituted characters with '_' as an alert to the user.
Al Everett
This is exactly what I was looking for. Thanks!
Jason
A: 

Probably you would have to replace # with ## to avoid this, I think this is caused because # is figured as Coldfusion keyword.

This should help.

Happy coding.

Ravia
There are no issues in Coldfusion. The issue is that it reads it as a named anchor on the page.
Jason
A: 

I can't comment yet, but Kevink's solution is good unless you need to perserve what you're replacing.

We ran into an instance where we needed to rename the filename but the filename needed to be somewhat preserved (user requirement). Simply removing special characters wasn't an option. As a result we had to handle each replace individually, something like.

<cfset newName = replace(thisFile, "##", "(pound)", "All")>
<cfset newName = replace(newName , "&", "(amp)", "All")>
<cffile action="rename"source = "#ExpandPath("\uploads\#thisFolder#\#thisFile#")#" destination = "#newName#">
Travis