Resources » .NET programming » ASP.NET/Web Applications

How to download files from web pages without exposing the URL


Last Updated:   Category: ASP.NET/Web Applications    
Author: Member Level: Gold    Points: 10


Do you want to allow your users to download files or display an image, but don't want to show the location of the file? Learn how to allow downloading without giving a direct url.



In many situations, we may want to allow users to download some files from the web site. And the easy and standard way of doing it is, providing a hyperlink, which users can click to start downloading the file. This simple method works great!

But in some cases, we may not want to expose the URL/location of the file. For example, you have some pictures in your web site, which you want only some of your friends to see for a short period of time. Or, you may own a dating site in which you want to show the pictures only to paid users and only for a limited period of time.

You can protect the pages by allowing only the registered users to view the page which has links to the protected files. But, they can note down the URL of the files and pass it to their friends or continue to use them even after their registration period expires. So, we may want to allow specific users to download some files without showing the URL to them.

One solutions is, provide a "Download" button and when user click on it, we will use the Response.WriteFile method to read the file from the secret location and output to the user.

The following sample shows how you can allow a user to download a specific file to the client machine, without exposing the location of the download file:

Response.ClearContent();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "Filename=Requirements.doc" );
Response.WriteFile( @"C:\MyFolder\Requirements.doc" );
Response.End();


Note that we have hardcoded the location of the actual download file. Instead of specifying the absolute path, you can use Server.MapPath( ... ) to map a relative path to absolute path. But the benefit of having the absolute path is, the location can be anywhere in the webserver computer. It need not be within the virtual folder.

Put the above code into your aspx file. If you have a button, which user have to click to start downloading, put the above code into the serverside click event of the button. When user click on the button, it will prompt the user to 'Open' or 'Save' the file.

The above sample shows how to download any binary file. You can specify the specific content type also. Some of the supported content types are :

"text/HTML"
"image/GIF"
"image/JPEG"
"text/plain"
"Application/msword" (for MS Word files)
"Application/x-msexcel" (for Excel files)


How the code works?

It is very simple. We are just programmatically reading the content of the file and sending as 'Response' to the user. So, instead of getting the html output from the webserver, the user's client browser will receive content of the download file. We have to specify the 'Content Type' and 'Content-Disposition' appropriately so that the client browser will not attempt to open the file in the browser itself.

Problem in downloading large files

The above approach fails in IIS 6.0 if the file size is very large. The problem occurs when the file size approaches 100 MB or more. The reason is for this problem is, we are attempting to stream the large file as a single block and the current release of IIS 6.0 fails to handle this properly. The work around is, read the file in small blocks and write to the response block by block. The below sample code will solve this problem.


// The secret file (path) to download.
string filepath = @"C:\Downloads\LargeDocument.doc";

// The file name used to save the file to the client's system..
string filename = System.IO.Path.GetFileName( filepath );

System.IO.Stream stream = null;
try
{
// Open the file into a stream.
stream = new System.IO.FileStream( filepath, System.IO.FileMode.Open,
System.IO.FileAccess.Read, System.IO.FileShare.Read );

// Total bytes to read:
long bytesToRead = stream.Length;

Response.ContentType = "application/octet-stream";
Response.AddHeader( "Content-Disposition", "attachment; filename=" +
filename );

// Read the bytes from the stream in small portions.
while ( bytesToRead > 0 )
{
// Make sure the client is still connected.
if ( Response.IsClientConnected )
{
// Read the data into the buffer and write into the
// output stream.

byte[] buffer = new Byte[10000];
int length = stream.Read( buffer, 0, 10000 );
Response.OutputStream.Write(buffer, 0, length);
Response.Flush();

// We have already read some bytes.. need to read
// only the remaining.
bytesToRead = bytesToRead - length;
}
else
{
// Get out of the loop, if user is not connected anymore..
bytesToRead = -1;
}
}
}
catch
{
// An error occurred.. do whatever you want in this situation !
}
finally
{
if ( stream != null )
{
stream.Close();
}
}


This problem is discussed in detail in the Microsoft Article :


Did you like this resource? Share it with your friends and show your love!

Responses to "How to download files from web pages without exposing the URL"
Author: Rajan Mistry    21 Jul 2004Member Level: Bronze   Points : 0
Hello..
U have shown very complex coding insted of this method u have to just use easy coding styles for acheveing this task ...
Getting My Point .
Thanks.



Author: RAJASEKARAN    21 Jul 2004Member Level: Bronze   Points : 0
THis is very good. But I have a small problem.
When I tried the first option, it never asked for
open or save.
When I tried the second,(Large file-using stream & buffer)
it did ask for the open & save option
But it did not clear the screen. My entire form
with download button was appearing.
Pls. suggest a way out



Author: Slawomir    22 Jul 2004Member Level: Bronze   Points : 0
fix:
after line:
Response.AddHeader( "Content-Disposition", "attachment; filename=" +
filename );

put:
Response.AddHeader("Content-Length", bytesToRead.ToString());



Author: Slawomir    22 Jul 2004Member Level: Bronze   Points : 0
fix:
after line:
Response.AddHeader( "Content-Disposition", "attachment; filename=" +
filename );

put:
Response.AddHeader("Content-Length", bytesToRead.ToString());



Author: Slawomir    22 Jul 2004Member Level: Bronze   Points : 0
fix:
after line:
Response.AddHeader( "Content-Disposition", "attachment; filename=" +
filename );

put:
Response.AddHeader("Content-Length", bytesToRead.ToString());



Feedbacks      

Post Comment:




  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:   Sign In to fill automatically.
    Email: (Will not be published, but required to validate comment)



    Type the numbers and letters shown on the left.


    Submit Article     Return to Article Index

    Subscribe to Subscribers
    Active Members
    Today
      Last 7 Daysmore...

      Awards & Gifts
      Talk to Webmaster Tony John

      Online Members

      More...
      Copyright © SpiderWorks Technologies Pvt Ltd., Kochi, India