Click here to Skip to main content
15,880,405 members
Articles / All Topics

ASP.NET: Downloading files from a UNC share

Rate me:
Please Sign up or sign in to vote.
3.75/5 (5 votes)
14 Feb 2017CPOL1 min read 26.8K   5  
Implementing a cross-browser solution for downloading files from a UNC share in ASP.NET applications

Table of Contents

The Scenario

I was working recently in an intranet application that had a download page. The output HTML was similar to the following:

HTML
<li><a class="download" 
href="\\MYSERVER\reports 2011\report1.zip" title="Report 1">Report 1</a></li>
<li><a class="download" 
href="\\MYSERVER\reports 2011\report2.zip" title="Report 2">Report 2</a></li>
<li><a class="download" 
href="\\MYSERVER\reports 2011\report 3.zip" title="Report 3">Report 3</a></li>
<li><a class="download" 
href="\\MYSERVER\reports 2011\report 4.zip" title="Report 4">Report 4</a></li>
<li><a class="download" 
href="\\MYSERVER\reports 2011\report 5&6.zip" title="Report 5&6">Report 5&6</a></li>

This was working fine in IE9, but not in other browsers. There was no action using Google Chrome, and using Firefox there was an error (HTTP Error 400 – Bad Request).

I tried to convert the file path to a file URI but it didn’t fix it. It continued to work on Internet Explorer only.

XML
<li><a class="download" 
href="file://MYSERVER/reports 2011/report1.zip" title="Report 1">Report 1</a></li>
<li><a class="download" 
href="file://MYSERVER/reports 2011/report2.zip" title="Report 2">Report 2</a></li>
<li><a class="download" 
href="file://MYSERVER/reports 2011/report 3.zip" title="Report 3">Report 3</a></li>
<li><a class="download" 
href="file://MYSERVER/reports 2011/report 4.zip" title="Report 4">Report 4</a></li>
<li><a class="download" 
href="file://MYSERVER/reports 2011/report 5&6.zip" title="Report 5&6">Report 5&6</a></li>

The solution was to create a custom ASP.NET download page. I also used jquery on the client side.

Step 1: Using jquery on the Client Side

The first step was to add an event handler to the download links. The request URI is encoded and is sent as a parameter to the download page. Creating an hidden iframe and setting the src attribute with the download link allows the file to be downloaded asynchronously.

JavaScript
$("a.download").bind("click", function (e) {
    e.preventDefault();
    var requestedFile = encodeURIComponent($(this).attr('href'));

    var iframe = document.createElement("iframe");
    iframe.src = 'Download.aspx?file=' + requestedFile;
    iframe.style.display = "none";
    document.body.appendChild(iframe); // triggers download page
});

Make sure you use encodeURIComponent function to encode special characters in the filename.

Step 2: Create an ASP.NET Download Page

This is the source code of the download page:

C#
protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        string requestFile = Request.QueryString["file"];

        if(string.IsNullOrEmpty(requestFile))
        {
            throw new FileNotFoundException("File to download cannot be null or empty");
        }

        // Get file name from URI string in C#
        // http://stackoverflow.com/a/1105614
        var uri = new Uri(requestFile);
        string filename = Path.GetFullPath(uri.LocalPath);
        var fileInfo = new FileInfo(filename);

        if(!fileInfo.Exists)
        {
            throw new FileNotFoundException("File to download was not found", filename);
        }

        // get content type based on file extension. Example:
        // http://stackoverflow.com/a/691599
        Response.ContentType = GetContentType(fileInfo.Extension);

        Response.AddHeader("Content-Disposition", 
                           "attachment; filename=\"" + fileInfo.Name + "\"");
        Response.WriteFile(fileInfo.FullName);
        Response.End();
    }
    catch(ThreadAbortException)
    {
        // ignore exception
    }
    catch(FileNotFoundException ex)
    {
        Response.StatusCode = (int) System.Net.HttpStatusCode.NotFound;
        Response.StatusDescription = ex.Message;
    }
    catch(Exception ex)
    {
        Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
        Response.StatusDescription = 
        string.Format("Error downloading file: {0}", ex.Message);
    }
}

Some notes:

This is necessary in order to make the download work with a UNC share (\\MYSERVER\….) or a file URI (file://….)

JavaScript
var uri = new Uri(requestFile);
string filename = Path.GetFullPath(uri.LocalPath);

To avoid filename truncating, it’s necessary to wrap the filename with quotes:

C#
Response.AddHeader("Content-Disposition", 
                       "attachment; filename=\"" + fileInfo.Name + "\"");

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Italy Italy
My name is Rui Jarimba and I was born in Madeira island, Portugal and I currently live in Rome, Italy.

I have more than 10 years of experience developing software using the .NET Framework and other technologies (Web development, Databases, ...).

Some of my professional interests are: software development best practices, software architecture, cloud computing, Continuous Integration (CI), Continuous Delivery (CD) and agile methodologies such as Scrum, Kanban, Lean and any other methodology that can help me to become a better and more productive software engineer.

I believe in good code - code that is readable, maintainable, reusable, testable and deployable. This means that I'm not the "quick and dirty" type, I write code for the medium/long term whenever possible.

Something else about me - I love music, I am an amateur photographer, not a big fan of gyms (I prefer to do some outdoor activity such as walking/hiking), big foodie (I love Mediterranean cuisine and my glass of wine!).

Comments and Discussions

 
-- There are no messages in this forum --