Friday, August 12, 2011

HttpPostedFile.FileName Beware…

Browser issues – you’ve gotta love them… 

Here’s the scenario…

We have an application that allows users to upload spreadsheets.  We parse the data in the spreadsheets to create new spreadsheets, save input to a data store, and a bunch of other useful functions.  Once the application was deployed, we started to get bug/issue reports on how the uploads were failing.  Typical user feedback: ‘…the Web site isn’t working;’ ‘…the uploading my database feature is broken;’ ‘…why can’t the Web site do it like Facebook?’  You get the idea…
We narrowed it down to an IE issue.  Most of the users were using IE8, while the developers were using Chrome, Firefox, and IE9.  Of course, the file upload and resulting file parsing was working fine for the developers and testers.  Why aren’t the users using Chrome, Firefox, IE9, Safari, etc…?  Well, because they are users Open-mouthed smile  Seriously though, the client’s organization is using IE8, so that’s what we should have used when developing and testing…

Continuing on…We couldn’t replicate the issue using IE9 in IE8 or IE7 mode; however, the bug/issue reports kept piling in…

Luckily, someone had an old VM with XP and IE8 installed.  So, we did a quick test using IE8, and sure enough, the ugly bug revealed itself.  Here’s a screenshot of what the YSOD could possibly look like (the paths and other revealing info is modified here, so the need for ‘possibly’).


Beyond the browser issue frustration, we couldn’t walk the code with VS2010, because the XP/IE8 VM did not have VS2010 installed.

What it all narrowed down to was how browsers offer up the file name (via HttpPostedFile.FileName property). All browsers (Chrome, FF, IE9, ...) but IE8- (IE8, 7, 6, ...) report ONLY the file name, while IE8- reports the fully qualified path on the client’s machine. The Fully Qualified Path (FQP) is the key here. Also, in IE9 in IE8 mode, the HttpPostedFile.FileName reports what IE9 would report and not IE8 (nice!).

The following is a snippet of the existing code (attachmentPath is the directory where the file will be saved to on the Server):

var fileName = Request.Files[i].FileName;
var filepath = Path.Combine(attachmentPath, fileName);

Do you see the issue? Well, when testing in all browsers but IE8-, this will work fine. However, in IE8-, the aforementioned snippet will result with a filepath of something like the following:

c:\directoryToStoreUploadedFiles\C:\Documents and Settings\xyz123\Desktop\ie8_testing.txt

while we are expecting the following:

c:\directoryToStoreUploadedFiles\ie8_testing.txt

So, make sure to parse out the file name correctly using the System.IO.Path.GetFileName() method. This method will return ONLY to file name (removing the directory path if it pre-pended).

The revised code snippet will work for all browsers:

var postedFile = Request.Files[i];
var fileName = Path.GetFileName(postedFile.FileName);
var filepath = Path.Combine(attachmentPath, fileName);

Now, we will always get what we are expecting.

If we would have looked at the MSDN documentation for the HttpPostedFile class (who does that??) - HttpPostedFile.FileName – we would have found the following documentation for the FileName property:

HttpPostedFile.FileName Property

Gets the fully qualified name of the file on the client.

Of course it does!?!? Not when the user is using Chrome, Firefox, IE9, or probably any other browser.

Simple solution, yet very difficult to track down. Something you may want to file away in your toolbox...

Thanks for reading…