Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

PRB: Response.WriteFile cannot download a large file


View products that this article applies to.

Symptoms

When you try to use the Response.WriteFile method to download a large file, the download may not respond, and then you may receive one of the following error messages:
The page cannot be displayed
-or-
Server Application Unavailable

The Web application you are attempting to access on this Web server is currently unavailable. Please hit the "Refresh" button in your Web browser to retry your request.

Administrator Note: An error message detailing the cause of this specific request failure can be found in the system event log of the web server. Please review this log entry to discover what caused this error to occur.
You may also receive the following message in the Application event log:

Aspnet_wp.exe (or W3wp.exe, for applications that run on Microsoft Internet Information Services [IIS] 6.0) stopped unexpectedly.

During this process, you may also notice an increase in the memory utilization of the Web server.

↑ Back to the top


Cause

The hardware configuration of the Web server computer determines the maximum file size that you can successfully download. When the ASP.NET worker process (Aspnet_wp.exe, or W3wp.exe for applications that run on Internet Information Services 6.0 [IIS]) runs the file download request, the file download dialog box appears. The ASP.NET worker process starts to send the data to the Microsoft Internet Information Services Process (Inetinfo.exe or Dllhost.exe). It does not wait for you to click OK.

Depending on the configuration of the computer, the IIS Process may process the data, or the data may be buffered in memory. When the file is large, the data is buffered in memory during communication between these two processes. This may cause an increase in the memory utilization on the server. The error occurs because of the memory constraints on the Web server.

↑ Back to the top


Workaround

To work around this issue, use any one of the following methods:
  • Obtain the data in small portions, and then move the data to the output stream for download. The following code demonstrates how to do this.

    Important When you set the value of the debug attribute of the compilation element to false in the Web.config file of your ASP.NET application, you must set the Server.ScriptTimeout property to an appropriate value for the file download size. By default, the Server.ScriptTimeout value is set to 90 seconds. However, when the debug attribute is set to true, the Server.ScriptTimeout value will be set to a very large 30,000,000 seconds. As a developer, you must be aware of the impact that this may have on the behavior of your ASP.NET Web application.

    Also, in the code that follows you must be aware of the parameter values that are used with the FileStream constructor. The enumeration values that are specifed make a significant impact on the functionality that is provided. For more information, refer to the FileStream link in the REFERENCES section.
    Visual Basic .NET Code
          Dim iStream As System.IO.Stream
    
          ' Buffer to read 10K bytes in chunk:
          Dim buffer(10000) As Byte
    
          ' Length of the file:
          Dim length As Integer
    
          ' Total bytes to read:
          Dim dataToRead As Long
    
          ' Identify the file to download including its path.
          Dim filepath As String = "DownloadFileName"
    
          ' Identify the file name.
          Dim filename As String = System.IO.Path.GetFileName(filepath)
    
          Try
             ' Open the file.
             iStream = New System.IO.FileStream(filepath, System.IO.FileMode.Open, _
                                                    IO.FileAccess.Read, IO.FileShare.Read)
    
             ' Total bytes to read:
             dataToRead = iStream.Length
             
             Response.ContentType = "application/octet-stream"
             Response.AddHeader("Content-Disposition", "attachment; filename=" & filename)
    
             ' Read the bytes.
                While dataToRead > 0
                    ' Verify that the client is connected.
                    If Response.IsClientConnected Then
                        ' Read the data in buffer
                        length = iStream.Read(buffer, 0, 10000)
    
                        ' Write the data to the current output stream.
                        Response.OutputStream.Write(buffer, 0, length)
    
                        ' Flush the data to the HTML output.
                        Response.Flush()
    
                        ReDim buffer(10000) ' Clear the buffer
                        dataToRead = dataToRead - length
                    Else
                        'prevent infinite loop if user disconnects
                        dataToRead = -1
                    End If
                End While
    
          Catch ex As Exception
             ' Trap the error, if any.
             Response.Write("Error : " & ex.Message)
          Finally
             If IsNothing(iStream) = False Then
                ' Close the file.
                iStream.Close()
             End If
             Response.Close()
          End Try
    
    Visual C# .NET Code
    	System.IO.Stream iStream = null;
    
    	// Buffer to read 10K bytes in chunk:
    	byte[] buffer = new Byte[10000];
    
    	// Length of the file:
    	int length;
    
    	// Total bytes to read:
    	long dataToRead;
    
    	// Identify the file to download including its path.
    	string filepath  = "DownloadFileName";
    
    	// Identify the file name.
    	string  filename  = System.IO.Path.GetFileName(filepath);
    
    	try
    	{
    		// Open the file.
    		iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, 
    					System.IO.FileAccess.Read,System.IO.FileShare.Read);
    
    
    		// Total bytes to read:
    		dataToRead = iStream.Length;
    
    		Response.ContentType = "application/octet-stream";
    		Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    
    		// Read the bytes.
      		while (dataToRead > 0)
    		{
    			// Verify that the client is connected.
    			if (Response.IsClientConnected) 
    			{
    				// Read the data in buffer.
    				length = iStream.Read(buffer, 0, 10000);
    
    				// Write the data to the current output stream.
    				Response.OutputStream.Write(buffer, 0, length);
    
    				// Flush the data to the HTML output.
    				Response.Flush();
    
    				buffer= new Byte[10000];
    				dataToRead = dataToRead - length;
    			}
    			else
    			{
    				//prevent infinite loop if user disconnects
    				dataToRead = -1;
    			}
    		}
    	}
    	catch (Exception ex) 
    	{
    		// Trap the error, if any.
    		Response.Write("Error : " + ex.Message);
    	}
    	finally
    	{
    		if (iStream != null) 
    		{
    			//Close the file.
    			iStream.Close();
    		}
    		Response.Close();
    	}
    	
    Replace DownloadFileName with the name of a file that is larger than 100 megabytes (MB).

    -or-
  • Provide a link for the user to download the file.

    -or-
  • Use Microsoft ASP 3.0 for the downloads or use Software Artisans FileUp with ASP.

    -or-
  • Create an ISAPI extension to download the file.

    -or-
  • Use FTP to download the file.

↑ Back to the top


Status

This behavior is by design.

↑ Back to the top


More information

Steps to Reproduce the Behavior

  1. In Microsoft Visual Basic .NET or in Microsoft Visual C# .NET, create a new Web Application project. By default, WebForm1.aspx is created.
  2. Drag a button object from the tool box to WebForm1.aspx.
  3. Double-click the button object to open the Click event in Code View.
  4. Paste the following code in the Button1 Click event.

    Visual Basic .NET Code
    	' Identify the file to download including its path.
    	Dim filepath As String = DownloadFileName
    
    	' Identify the file name.
    	Dim filename As String = System.IO.Path.GetFileName(filepath)
    
    	Response.Clear()
    	
    	' Specify the Type of the downloadable file.
    	Response.ContentType = "application/octet-stream"
    
    	' Set the Default file name in the FileDownload dialog box.
    	Response.AddHeader("Content-Disposition", "attachment; filename=""" & filename & """")
    
    	Response.Flush()
    
    	' Download the file.
    	Response.WriteFile(filepath)

    Visual C# .NET Code
    	// Identify the file to download including its path.
    	string filepath = DownloadFileName;
    
    	// Identify the file name.
    	string filename = System.IO.Path.GetFileName(filepath);
    
    	Response.Clear();
    
    	// Specify the Type of the downloadable file.
    	Response.ContentType = "application/octet-stream";
    
    	// Set the Default file name in the FileDownload dialog box.
    	Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    
    	Response.Flush();
    
    	// Download the file.
    	Response.WriteFile(filepath);
  5. Replace DownloadFileName with the name of a file that is larger than 100 MB.
  6. On the Debug menu, click Start.
  7. Click Button1.

↑ Back to the top


References

For more information, click the following article numbers to view the articles in the Microsoft Knowledge Base:
307603 How to write binary files to the browser using ASP.NET and Visual Basic .NET
306654 How to write binary files to the browser using ASP.NET and Visual C# .NET
For more information, visit the following Microsoft Developer Network (MSDN) Web site:

↑ Back to the top


Keywords: KB812406, kbprb, kbdownload, kbweb, kbwebforms, kbwebserver

↑ Back to the top

Article Info
Article ID : 812406
Revision : 7
Created on : 11/21/2007
Published on : 11/21/2007
Exists online : False
Views : 1129