Microsoft KB Archive/812406

= PRB: Response.WriteFile cannot download a large file =

Article ID: 812406

Article Last Modified on 11/21/2007

-

APPLIES TO


 * Microsoft Web Services Enhancements for Microsoft .NET 1.1
 * Microsoft ASP.NET 1.1
 * Microsoft ASP.NET 1.0

-





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 &quot;Refresh&quot; 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.



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.



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 = &quot;DownloadFileName&quot;

' 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 = &quot;application/octet-stream&quot; Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot; & 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(&quot;Error : &quot; & 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 = &quot;DownloadFileName&quot;;

// 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 = &quot;application/octet-stream&quot;; Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot; + 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(&quot;Error : &quot; + ex.Message); }   finally {       if (iStream != null) {           //Close the file. iStream.Close; }       Response.Close; } Replace  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.

<div class="status_section">

STATUS
This behavior is by design.

<div class="moreinformation_section">

Steps to Reproduce the Behavior
<ol> In Microsoft Visual Basic .NET or in Microsoft Visual C# .NET, create a new Web Application project. By default, WebForm1.aspx is created.</li> Drag a button object from the tool box to WebForm1.aspx.</li> Double-click the button object to open the Click event in Code View.</li>  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 = &quot;application/octet-stream&quot;

' Set the Default file name in the FileDownload dialog box. Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot;&quot;&quot; & filename & &quot;&quot;&quot;&quot;)

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 = &quot;application/octet-stream&quot;;

// Set the Default file name in the FileDownload dialog box. Response.AddHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=&quot; + filename);

Response.Flush;

// Download the file. Response.WriteFile(filepath); </li> Replace  with the name of a file that is larger than 100 MB.</li> On the Debug menu, click Start.</li> Click Button1.</li></ol>

<div class="references_section">

Notice
The third-party products that are discussed in this article are manufactured by companies that are independent of Microsoft. Microsoft makes no warranty, implied or otherwise, regarding the performance or reliability of these products.

Keywords: kbdownload kbwebserver kbwebforms kbweb kbprb KB812406

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.