7

Web APIを使用して大きなファイルをクライアントにストリーミングしていますが、ダウンロードが成功したかどうかをログに記録したいと思います。つまり、サーバーがファイルのコンテンツ全体を送信した場合です。

HttpResponseMessageデータの送信が完了したときにコールバックまたはイベントを取得する方法はありますか?

おそらくこのようなもの:

var stream = GetMyStream();
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");    
// This doesn't exist, but it illustrates what I'm trying to do.
response.OnComplete(context =>
{
    if (context.Success)
        Log.Info("File downloaded successfully.");
    else
        Log.Warn("File download was terminated by client.");
});
4

3 に答える 3

5

編集:私は今、実際の接続を使用してこれをテストしました(フィドラー経由)。

例外をチェックする独自のアクションを継承StreamContentして追加しました。OnComplete

public class StreamContentWithCompletion : StreamContent
{
    public StreamContentWithCompletion(Stream stream) : base (stream) { }
    public StreamContentWithCompletion(Stream stream, Action<Exception> onComplete) : base(stream) 
    { 
        this.OnComplete = onComplete; 
    }

    public Action<Exception> OnComplete { get; set; }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        var t = base.SerializeToStreamAsync(stream, context);
        t.ContinueWith(x =>
        {
            if (this.OnComplete != null)
            {
                // The task will be in a faulted state if something went wrong. 
                // I observed the following exception when I aborted the fiddler session: 
                // 'System.Web.HttpException (0x800704CD): The remote host closed the connection.'
                if (x.IsFaulted)
                    this.OnComplete(x.Exception.GetBaseException());
                else
                    this.OnComplete(null);
            }
        }, TaskContinuationOptions.ExecuteSynchronously);
        return t;
    }
}

それから私はそれを次のように使用します:

var stream = GetMyStream();
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContentWithCompletion(stream, ex =>
{
    if (ex == null)
        Log.Info("File downloaded successfully.");
    else
        Log.Warn("File download was terminated by client.");
});
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");    
return response;
于 2012-12-20T02:29:16.217 に答える
3

すべてが正常であるという直接的な信号があるかどうかはわかりませんが、トリックを使用して、接続を終了する直前と、ファイルを完全に送信した直後に接続が存在することを確認できます。

たとえばResponse.IsClientConnected、クライアントがまだ接続されている場合は true が返されるため、次のように確認できます。

// send the file, make a flush
Response.Flush();
// and now the file is fully sended check if the client is still connected
if(Response.IsClientConnected)
{
  // log that all looks ok until the last byte.
}
else
{
  // the client is not connected, so maybe have lost some data
}

// and now close the connection.
Response.End();
于 2012-12-20T00:50:14.563 に答える
1

サーバーがファイルのコンテンツ全体を送信した場合

実際には何もすることはありません:)

これは非常に単純に聞こえるかもしれませんが、クライアントが途中でキャンセルするのではなく、サーバーが配信することに関心がある場合は、例外が発生したかどうかがわかります。WebApi ではなく、IsClientConnectedASP.NET に基づいています。HttpResponse

于 2012-12-20T09:54:50.307 に答える