PRB: Response.WriteFile は、サイズの大きなファイルをダウンロードできません。

現象

Response.WriteFileメソッドを使用して、サイズの大きなファイルをダウンロードしようとするとダウンロードには応答せず、次のエラー メッセージのいずれか表示される場合があります。
ページを表示できません。
- または -
サーバー アプリケーションは使用できません。

この Web サーバーにアクセスしようとする Web アプリケーションは現在利用可能ではありません。要求を再試行するのには Web ブラウザーで [更新] ボタンをクリックしてください。

管理者メモ: web サーバーのシステム イベント ログにこの特定の要求エラーの原因を説明するエラー メッセージを確認できます。このエラーが発生の原因には、このログ エントリを確認してください。
アプリケーション イベント ログに次のメッセージもあります。 この処理中に場合もあります、Web サーバーのメモリ使用率が増加します。

原因

Web サーバー コンピューターのハードウェア構成では、正常にダウンロードできるファイルの最大サイズを決定します。ASP.NET ワーカー プロセス (Aspnet_wp.exe、またはインターネット インフォメーション サービス 6.0 (IIS) で実行されるアプリケーションの W3wp.exe) では、ファイルのダウンロード要求を実行するときは、ファイルのダウンロード] ダイアログ ボックスが表示されます。Microsoft インターネット インフォメーション サービス プロセス (Inetinfo.exe または Dllhost.exe) にデータを送信する ASP.NET ワーカー プロセスを開始します。[Ok]をクリックするは待機しません。

コンピューターの構成によって IIS プロセスがデータの処理またはメモリ内データをバッファリングすることがあります。ファイルのサイズが、これら 2 つのプロセス間の通信中にデータがメモリにバッファリングされてがします。サーバー上のメモリ使用率の増加があります。エラーは、Web サーバー上のメモリの制約のために発生します。

回避策

この問題を回避するのには次の方法のいずれかを使用します。
  • 小さな部分は、内のデータを入手し、ダウンロード用の出力ストリームにデータを移動します。次のコードでは、これを行う方法を示します。

    重要 False を指定する、ASP.NET アプリケーションの Web.config ファイルでデバッグコンパイル要素の属性の値を設定するときは、ファイルのダウンロード サイズの適切な値にServer.ScriptTimeoutプロパティを設定する必要があります。 既定では、 Server.ScriptTimeoutの値は 90 秒に設定します。 ただし、 debug属性をtrueに設定すると、ときにServer.ScriptTimeoutの値は設定から非常に大きな 30,000,000 秒。 開発者は、この可能性がある ASP.NET Web アプリケーションの動作に影響を認識する必要があります。

    また、あなたをフォローするコードにする必要がありますFileStreamコンス トラクターで使用されるパラメーターの値に注意してください。指定されている列挙値は、提供される機能に大きな影響を確認します。詳細については、 FileStreamのリンクを参照してください、
    セクションを参照
    Visual Basic .NET のコード
          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 コード
    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();
    }

    100 メガバイト (MB) よりも大きいファイルの名前とDownloadFileNameを交換してください。

    - または -
  • ユーザーがファイルをダウンロードするためのリンクを提供します。

    - または -
  • ダウンロードのマイクロソフトの ASP 3.0 を使用してまたは asp ソフトウェア Artisans FileUp を使用します。

    - または -
  • ファイルをダウンロードする ISAPI 拡張機能を作成します。

    - または -
  • ファイルをダウンロードするのにには、FTP を使用します。

状況

これは仕様による動作です。

詳細

現象を再現する手順を実行します。

  1. Microsoft Visual Basic .NET または Microsoft Visual C# .NET では、新しい Web アプリケーション プロジェクトを作成します。既定では、WebForm1.aspx が作成されます。
  2. WebForm1.aspx に、[ツール] ボックスから、ボタン オブジェクトをドラッグします。
  3. Clickイベントをコード ビューで開くには、ボタン オブジェクトをダブルクリックします。
  4. Button1 のクリックしてイベントに次のコードを貼り付けます。

    Visual Basic .NET のコード
    ' 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 コード
    // 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. DownloadFileNameを 100 MB を超えるファイルの名前に置き換えます。
  6. [デバッグ] メニューで、次のようにクリックします。
    起動します。
  7. [ Button1を] をクリックします。

関連情報

詳細については、マイクロソフトサポート技術記事を表示する次の資料番号をクリックしてください。

ASP.NET と Visual Basic .NET を使用してブラウザーにバイナリ ファイルを作成する方法を307603

306654 ASP.NET と Visual C# .NET を使用してブラウザーにバイナリ ファイルを書き込む方法

詳細については、次の Microsoft Developer Network (MSDN) Web サイトを参照してください。
この資料に記載されているサードパーティ製品は、マイクロソフトと関連のない他社の製品です。明示または黙示にかかわらず、これらの製品のパフォーマンスや信頼性についてマイクロソフトはいかなる責任も負わないものとします。
プロパティ

文書番号:812406 - 最終更新日: 2017/02/18 - リビジョン: 2

フィードバック