Thursday, January 10, 2013

Work Around to Opening up a Local Folder from an HTML Link

Introduction (solution below)
In general in web programming at one point you may need to or be asked to open up a local folder from a html link. This is something that used to work with older versions of IE, but just like everything in older versions of IE it was not a good idea just because you could do it. It was a huge security risk. Basically one can say that if your browser is able to access your file system without your consent by you clicking on anything, it is security risk. I remember once while I was browsing around on strange edges and corners of the internet, I clicked on a DoubleClick Ad Banner and it wrecked my weak computer by installing without asking me about 10 programs that hijacked my computer and my browser. I tried uninstalling all of them, but even after uninstalling the programs my computer was running very badly, so I ended up having to reformat because it was so bad. That is the best example I can give of a browser security risk and that happened in a old version of IE.

The Question
How do I open up a local folder from an HTML link on a web page? This question has been asked in many forms repeatedly on stackoverflow and other places on the net. I am using this question as my model:
http://stackoverflow.com/questions/5246292/open-local-folder-from-link

The Answer
My co-worker and I were trying to figure out the best way to solve this and we went through a lot of trial and error until we found out that there were files ending in *.url that were very simplistic as opposed to *.lnk files which are binaries and not plain text! Don't bother trying to make a *.lnk (shortcut file) from the server side because this type of file requires shell access, you need the shell from the client side, not the server side in order to do this correctly.

My co-worker/friend contributed an answer to the question on Stack Overflow here.

Basic Steps
  1. Take the folder's path and put it into a URL file like so:
    [InternetShortcut]
    URL=C:\somefolder\that\the\user\wants\
    I got this solution from here.
  2. Make the "folder path" available for download via a LinkButton or similar mechanism
  3. Before the user can download the file, IIS has to allow for the *.url MIME type otherwise IIS will return a 404 error.
    A. Open the IIS Manager and for your application/site in Features view locate the IIS section and find the feature called "MIME Types", open it.
    B. In the top right click the "Add..." link.
    C. In the modal window enter ".url" into the "File name extension" filed and enter “application/internet-shortcut” into the "MIME type" field.
    D. You will have to restart IIS in order for these settings to be applied. Do so by entering the following into CMD: "IISRESET /restart" - I got this solution from here from the last paragraph.
  4. The user has to open the file and it will open the specified folder (if it exists on their system)
Viola same effect. One more step for the user, but really the only way to get this to work right now that we could figure out.
3-A
3-B
3-C
The Code
Here is some starter code to help you get the idea.

//This is a hacked up excerpt from code I am using at work. This is from a Details View control.
//I am intercepting a click event from a Link Button in my control and processing it here.
protected void dv_ItemCommand(object sender, DetailsViewCommandEventArgs e)
{
 if (e.CommandName.ToLower() == "download")
 {
  //Get the bytes from the string that will ultimately be the the file's content
  byte[] arrContent = System.Text.Encoding.UTF8.GetBytes("[InternetShortcut]\nURL=" + e.CommandArgument);

  //Let the user download the bytes using a different name
  Response.ClientFileDownload(arrContent, "ProductDirectory.url"); //This is a custom method I wrote defined below
 }
}

/// 
/// Download a file to the client through their browser using the raw bytes of a file
/// 
/// 
/// the raw bytes of the requested file
/// (Optional) the name of the file being requested - if not provided a random file name is assigned with a "tmp" extension
public static void ClientFileDownload(this HttpResponse response, byte[] file, string fileName = null)
{
 //http://stackoverflow.com/questions/629675/how-to-response-write-bytearray
 if (file != null)
 {
  if (string.IsNullOrEmpty(fileName))
   fileName = Path.GetRandomFileName();

  response.ContentType = "application/x-msdownload";
  response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
  response.BinaryWrite(file);
  response.End();
 }
 else
  throw new Exception("The provided file was null.");
}

Resources
My co-worker and I used all of the following resources to come up with an answer. So I am giving credit where credit is due, please check out the links if you have some time.

No comments:

Post a Comment