1

私の質問はこの投稿に似ていますが、IIS、ASP.NET、および C# を使用して同じことを行う必要があります。

このクラスのどのメソッドHttpResponseも、データが送信されたかどうかにかかわらずフィードバックを提供せず、TransmitFile()その仕事をする (またはしない) だけで、結果を知る手段を提供しません。

私はプロパティを使用することを考えていましたが、フィルタはフィードバックを提供しない に.Filter基づいて います。HttpResponseStream

何か案は?

4

2 に答える 2

1

いくつかのテストの後、問題に対する次の解決策を思いつきました。TransmitFile() には重大な制限が 1 つあります。送信する前にファイル全体をメモリに読み込みます。これは、大きなファイルには非常に悪いことです。したがって、基本的には手動のチャンクに頼り、各チャンクの後にクライアントが接続されているかどうかを確認しました。

context.Response.Clear();
context.Response.BufferOutput = false;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + originalFilename);
context.Response.AddHeader("Content-Length", fileLength.ToString());
context.Response.Cache.SetNoStore();

context.Response.Flush();

downloadFailed = !context.Response.IsClientConnected;

int thisChunk;
long offset = 0;
int chunkSize = 1024 * 8;
byte[] bytes = new byte[chunkSize];

FileStream r = File.OpenRead(localFilename);

while((offset < fileLength) && !downloadFailed)
{
    if((fileLength - offset) < chunkSize)
    {
        thisChunk = (int)(fileLength - offset);
    }
    else
    {
        thisChunk = chunkSize;
    }

    r.Read(bytes, 0, chunkSize);

    try
    {
        context.Response.BinaryWrite(bytes);
        context.Response.Flush();

        if(!context.Response.IsClientConnected)
        {
            downloadFailed = true;
        }
    }
    catch(ObjectDisposedException ex1)
    {
        // Stream is closed, nothing written
        break;
    }
    catch(System.IO.IOException ex3)
    {
        // I/O error, unknown state, abort
        Trace.Write(ex3);
        break;
    }

    offset += thisChunk;
}

if(!downloadFailed)
{
    // now update the file, statistics, etc
}

context.Response.Flush();

HttpContext.Current.ApplicationInstance.CompleteRequest();

最適なサイズを見つけるには、チャンク サイズを少し調整する必要があります。しかし、基本的にはこのように確実に動作します。

于 2010-02-18T12:48:33.313 に答える
0

Response.IsClientConnectedお電話の上、ご確認くださいTransmitFile

于 2010-02-18T02:35:21.333 に答える