0

I let users upload files using the asp.net upload control. I have a repeater on a page that list the files and users can click to download them:

    protected void grdFiles_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType != DataControlRowType.DataRow) return;

        var fileNameFull = Common.FileHelper.UploadPath + e.Row.Cells[0].Text;

        Request.MapPath(fileNameFull);

        var hyp = new HyperLink
                      {
                          NavigateUrl = fileNameFull,
                          Text = e.Row.Cells[0].Text,
                      };
        e.Row.Cells[0].Controls.Add(hyp);
    }

this works fine when the files are on the same drive as the web application, fileNameFull looks like: ~\Uploads\some pdf.pdf

The requirement now is that files are going to be stored on a different drive so my question is how can I achieve this? Request.MapPath obviously expects a virtual path.

The files needs to be exposed to users over the web, security is not the main concern.

Thanks in advance.

sundar
  • 1,760
  • 12
  • 28
John Doe
  • 188
  • 1
  • 14

3 Answers3

1

You can't create a hyperlink to a file that is not hosted within the web site. But you can create an http handler to serve the file. The http handler could accept an identifier for the file in the query string and write the file out to the response:

public class YourHttpHandler: IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string filePath = Common.FileHelper.UploadPath + context.Request.QueryString["file"];
        context.Response.ContentType = "your content type";
        context.Response.WriteFile(filePath);
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

Then in the bind event of your page, you could set the NavigateUrl to the handler, with an identifier for the file in the query string. Something like this:

var hyp = new HyperLink
                      {
                          NavigateUrl = "~/YourHttpHandler.ashx?file=" + e.Row.Cells[0].Text,
                          Text = e.Row.Cells[0].Text,
                      };
Glen Hughes
  • 4,712
  • 2
  • 20
  • 25
  • thanks that was easy enough, one further question though, I won't know what content type it is (simple text/word/photos/pdf) so how do I handle this best, any links for further reading? – John Doe Aug 15 '12 at 06:30
  • nevermind, I use the dictionary solution from here http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on-the-file-signature – John Doe Aug 15 '12 at 07:15
0

You can create yours custom VirtualPathProvider that will allow you to map different files to different virtual paths.

Notes

When you inherit from VirtualPathProvider, you must override the following members:

- FileExists
- GetFile

If your custom VirtualPathProvider class supports directories in the virtual file system, you must override the following members.

- DirectoryExists
- GetDirectory
user854301
  • 5,383
  • 3
  • 28
  • 37
0

First off, you are totally ignoring the result of calling

Request.MapPath(fileNameFull);

Is that intentional? Or did you mean to write

fileNameFull = Request.MapPath(fileNameFull);?

Second, you will need to create a Virtual Directory in IIS, which will be mapped to the UNC path of the location where the files will be stored.

For example, you could map the virtual path /Uploads/ to the UNC path \\extraserver\fileshare\uploads\.

There are security issues to manage (your web site normally runs in an account that does not have domain access, so it wouldn't normally be able to connect to shares on other servers -- you can take care of this by picking a domain user to use for connecting).

Then ignore the Request.MapPath path, and also your Common.FileHelper.UploadPath part.

You'll just provide the http://mywebserver/mywebsite/Uploads/ part (or however you want to make that, where Uploads is the Virtual Directory pathname) concatenated with the name of the file.

Alan McBee
  • 4,202
  • 3
  • 33
  • 38