Downloading any file to the browser – Part II: using ASP.NET

Following an article on how to do this using ASP 3.0, we’ll see how to accomplish the same effect using ASP.NET. Using streams, we can provide a file to the user without the need for FTP or any interference of the Internet Information Server (IIS).

The Code

Create an ASPX file, called download.aspx. This file takes a filename as a parameter, and returns the contents of that file in the response stream. For example, if you wanted to have the users download a file called logo.gif residing in the images folder, you would do so like this:

<a href="download.aspx?file=/images/logo.gif">Download the logo image</a>

The complete code in VB.NET:

<%@ Page language="vb" runat="server" explicit="true" strict="true" %>
<script language="vb" runat="server">
Sub Page_Load(Sender As Object, E As EventArgs)
	Dim strRequest As String = Request.QueryString("file") '-- if something was passed to the file querystring
	If strRequest <> "" Then 'get absolute path of the file
		Dim path As String = Server.MapPath(strRequest) 'get file object as FileInfo
		Dim file As System.IO.FileInfo = New System.IO.FileInfo(path) '-- if the file exists on the server
		If file.Exists Then 'set appropriate headers
			Response.Clear()
			Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
			Response.AddHeader("Content-Length", file.Length.ToString())
			Response.ContentType = "application/octet-stream"
			Response.WriteFile(file.FullName)
			Response.End 'if file does not exist
		Else
			Response.Write("This file does not exist.")
		End If 'nothing in the URL as HTTP GET
	Else
		Response.Write("Please provide a file to download.")
	End If
End Sub
</script>

First, we check to see if something was passed in the QueryString, and if nothing was, then we output an error. Then we run our code only if the file actually exists on the web server. All the conditional statements are there to avoid errors in our output. Two headers are needed: one for telling the browser to save the stream as an attachment, and the other to set the length of the stream so that the browser will properly display a download progress bar. The main method here is the WriteFile, which writes the contents of the file in the response stream.

The ContentType header which is added, sets your MIME type so that the browser knows what kind of file this is. You can see a listing of all the MIME types supported on your server, by looking in your web server’s properties under MIME types. For example, if you are serving an MS Word file, this would be “application/msword“. Octet-stream, which is used above, is a straight binary and acts as a catch-all datatype: when you define something with this datatype, the web server will simply let you download or open the file.

This code should work for all files on Windows systems, but there are some issues with Macintosh systems. Specifically, you may not be able to download the files, instead they will always open up in the browser as expected.

17 Responses to Downloading any file to the browser – Part II: using ASP.NET

  • mhorkpheus

    Thanks a lot! it works! thank you!

  • delamodedan

    Brilliant! Perfect for what I was trying to acheive. Thanks so much for posting!

  • Bruce

    Great! Thanks very much for posting this. This is particularly useful for those looking to download a file from the App_Data folder.

  • RCEI

    “Thread was being aborted”
    Just in case:
    http://support.microsoft.com/kb/312629/en-us
    PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer

  • Solomon

    What if you want to allow for only specific file extensions to be downloadable and not use this method for any other extensions? Cause I can see this being a problem with security, since you can pass any file into this (including .aspx, .html, etc. etc.).

    • Evagoras Charalambous

      @Solomon,

      Sorry for the delay, this one got away from me. You could easily achieve what you want, by placing a check for the “file” passed in. Say you wanted to allow only JPG files to be downloaded, you could add something like:

      If Right(Request.QueryString("file"),4) = ".jpg" Then
          '... proceed with download
      Else
           Response.Clear()
           Response.Write("File extension not supported.")
           Response.End
      End If
      

      You can then get as creative as you need when checking the file that was passed through the URL.

  • Jessie

    Dude, I have been looking for a simple answer to a simple question for hours. Thanks for posting that! Great job !

  • Harley63

    Fantastic! You will not believe how many web sites including MSDN i have trawled through to get a solution to what I felt was a simple taks. Brilliant! Thank you so much.

  • tee

    What modification is required if download without “Save As” prompting, ie save as temp file to download folder as per browser settings?

    What I am trying to achieve if click on a link, download the file and send to default printer.

    • Evagoras Charalambous

      @tee,

      I am not sure how you would do that. Due to security concerns, browsers will not let you automatically download content from a website unless you specifically give each file permission to do so. You can then opt to download it in the browser’s default download folder if you like – that’s up to the way you have your browser set up. But to get it there, I believe you have to explicitly approve to download it.

      Please correct me if I am wrong. I would love to see a solution like you describe.

  • Chandan singh

    ‘Code in ASP to download pdf files in a zip folder

    Dim File, Archive
    ‘ Create a temp file to hold the archive
    Set File = Server.CreateObject(“ActiveFile.File”)

    File.CreateTemp Application(“MapPath”) & “files\tmpfiles”

    ‘ Create the ZIP archive
    Set Archive = Server.CreateObject(“ActiveFile.Archive”)
    Archive.NewArchive File, 0
    Archive.Add “filename”
    Archive.SaveArchive
    Set Archive = Nothing
    Response.AddHeader “Content-Disposition”, “attachment; filename=YourSelectedPdfs.zip”
    File.Download “application/x-zip-compressed”, Now(), True, True

    The code works till the second last line. I can see the that there is a temp file created with the pdf files. But the moment “file.download” is executed it throws an error on server saying ” The web page can not be found”. Can somebody help me to find out what is wrong in last line of the code.

    • Chandan singh

      Missed few information in the above comment.

      The code works fine on Windows server 2003. But I get errors on Windows server 2008 R2.

    • Evagoras Charalambous

      If you are getting a 404 error, make sure your IIS is configured to allow you to download ZIP files. Here’s a good explanation of the possible issue and how to fix it:
      http://www.adamwlewis.com/articles/iis-7-not-serving-files-4047-error

      Summary of changes here:

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
        <system.webServer>
          <security>
            <requestFiltering>
              <fileExtensions allowUnlisted="true" >
                <remove fileExtension=".zip" />
                <add fileExtension=".zip" allowed="true"/>
              </fileExtensions>
            </requestFiltering>
          </security>
        </system.webServer>
      </configuration>
      

      The same would apply for any type of files you are having an issue with – you would need to add the file extension permission in the web.config of the website (or machine.config of the server to change all the sites).

      • Chandan singh

        I made the suggested change but still I am receiving an error saying “Internet Explorer cannot display the webpage” in IE and ” This webpage is not available” in Chrome.

        Downloading files is happening when I use the code you have given in the starting of the article. But as I have to download multiple files, I am using ActiveFile component to accumulate all the files through a loop and at the end I am using the last 2 line
        Response.AddHeader “Content-Disposition”, “attachment; filename=YourSelectedPdfs.zip”
        File.Download “application/x-zip-compressed”, Now(), True, True

        This works perfectly with Web Server 2003 but not sure whats going wrong with WebServer 2008.

        • Evagoras Charalambous

          Wait, so, are you trying to download numerous files one by one? Because I don’t think you can do that. To manage something like that you would probably need to stream each file in a separate popup via Javascript, and you will run into issues with popup blockers anyway.
          If you are zipping all the files and downloading the zip file instead, then It should work. You could try something like DotNetZip, a free component that works nicely. You could then create your PDF files, place them on the server, loop through and create a zip file using that component, and then clear the buffer and send the zip file along to the browser. Theoretically, that should work across all browsers and servers, as long as you have made sure to enable zip file download from your server.

  • wria

    thank you so much, it’s a very Good way for download.

  • shravan

    Hi,
    Could you please let me know how do we handle the same thign if the files are stored in a different shared folder. As my requirement is to get the files from a shared folder which is located in different path and cant afford to store them in root node. Please suggest . Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *