0

安全な方法でファイルをブラウザーにストリーミングする ashx ハンドラーを作成しました。これらのファイルにアクセスする権限をユーザーに付与したいと考えています。

問題は、大きなファイル (+40 MB) をストリーミングすると、セッションが失われ、ブラウザーのダウンロードが ~40 MB 後に突然中断されることです。

240 分前にタイムアウトしないように web.config を構成しています。

これをローカルでテストしても同じ問題は発生しませんが、共有ホストでテストすると発生します。

誰でも私を正しい方向に向けることができますか?

私は Reponse.Clear() の有無にかかわらず試しました

public void ProcessRequest(HttpContext context)
    {
        int id;

        if (new Core.SecurityManager().CurrentUser != null)
        {

            try
            {
                id = Convert.ToInt32(context.Request.QueryString["id"]);
            }
            catch
            {
                throw new ApplicationException("id could not  be parsed.");
            }

            string filename = new DocumentFactory().SelectDocumentById(id).Filename;

            string filePath = context.Server.MapPath("~/uploads/" + filename);

            //context.Response.Clear();

            context.Response.AddHeader("content-disposition", "attachment; filename=" + filename);

            context.Response.ContentType = "application/octet-stream";

            context.Response.WriteFile(filePath);

            //context.Response.Flush();

            //context.Response.End();
        }
        else
        {
            throw  new AuthenticationException();
        }

    }

Web.config:

 <sessionState mode="InProc" cookieless="false" timeout="240"></sessionState>

編集は次のように試みましたが、それでもダウンロードは中断されます:

FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);

            byte[] byteArray = new byte[fs.Length];

            using (MemoryStream ms = new MemoryStream(byteArray))
            {
                long dataLengthToRead = ms.Length;
                int blockSize = dataLengthToRead >= 5000 ? 5000 : (int)dataLengthToRead;
                byte[] buffer = new byte[dataLengthToRead];
                context.Response.Clear();


                // Clear the content of the response
                context.Response.ClearContent();
                context.Response.ClearHeaders();


                // Buffer response so that page is sent
                // after processing is complete.
                context.Response.BufferOutput = true;


                // Add the file name and attachment,
                // which will force the open/cance/save dialog to show, to the header
                context.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);


                // bypass the Open/Save/Cancel dialog
                //Response.AddHeader("Content-Disposition", "inline; filename=" + doc.FileName);


                // Add the file size into the response header
                context.Response.AddHeader("Content-Length", fs.Length.ToString());


                // Set the ContentType
                context.Response.ContentType = "application/octet-stream";


                // Write the document into the response
                while (dataLengthToRead > 0 && context.Response.IsClientConnected)
                {
                    Int32 lengthRead = ms.Read(buffer, 0, blockSize);
                    context.Response.OutputStream.Write(buffer, 0, lengthRead);
                    //Response.Flush();
                    dataLengthToRead = dataLengthToRead - lengthRead;
                }

                context.Response.Flush();
                context.Response.Close();
            }


            // End the response
            context.Response.End();

フルパスを追加してブラウザを介してファイルに直接アクセスすると、ダウンロードに問題はありません。

4

1 に答える 1

0

IISで大きなファイルを配信する正しい方法は次のオプションですが、

  1. WebLimitsでMinBytesPerSecondをゼロに設定します(IISは、より小さなサイズの転送でキープアライブ接続を保持しているクライアントを閉じることを選択するため、これは確かにパフォーマンスの向上に役立ちます)

  2. より多くのワーカープロセスをアプリケーションプールに割り当てます。これは8に設定しました。これは、サーバーがより大きなファイルを配布している場合にのみ実行する必要があります。これにより、他のサイトのパフォーマンスが低下することは確かですが、配信が向上します。このサーバーにはWebサイトが1つしかなく、巨大なファイルを配信するだけなので、8に設定しました。

  3. アプリプールのリサイクルをオフにする

  4. セッションをオフにする

  5. バッファリングをオンのままにします

  6. 次の各手順の前に、Response.IsClientConnectedがtrueであるかどうかを確認してください。そうでない場合は、あきらめて何も送信しないでください。

  7. ファイルを送信する前にContent-Lengthを設定する

  8. 応答をフラッシュする

  9. 出力ストリームに書き込み、定期的にフラッシュします

于 2012-06-27T11:32:49.960 に答える