C# Tutorials and offshore development in India
    Tutorials   Resources   Forum   Communities   Interview   Jobs   Projects   Offshore Development    
Silverlight Tutorials | Mentor | Code Converter | Articles | Code Factory | Computer Jokes | Members | Peer Appraisal | IT Companies | Bookmarks | Revenue Sharing |


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...

New Feature: Community Sites: Create your own .NET community website and start earning from Google AdSense ! It's Free !




How to allow downloading of files without exposing the URL


Posted Date: 16 Jun 2004    Resource Type: Articles    Category: Web Applications

Posted By: Tony John       Member Level: Gold
Rating:     Points: 10



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 :




Responses

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      
Popular Tags   What are tags ?   Search Tags  
(No tags found.)

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: ASP.NET Validation Behavior Cleared Out
Previous Resource: Various session storage facilities in ASP.NET and performance implications
Return to Discussion Resource Index
Post New Resource
Category: Web Applications


Post resources and earn money!
 
Related Resources



dotNet Slackers   BizTalk Adaptors    Web Design

conference calls

Contact Us    Privacy Policy    Terms Of Use