ASP.NET Web API完成向客户端发送时是否有通知

时间:2012-12-20 00:41:03

标签: asp.net asp.net-web-api

我正在使用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.");
});

3 个答案:

答案 0 :(得分: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();

答案 1 :(得分:3)

编辑:我现在使用真正的连接(通过提琴手)测试了这个。

我继承了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;

答案 2 :(得分:1)

  

如果服务器发送了文件的全部内容

实际上无事可做:)

这可能听起来非常简单,但您会知道是否引发了异常 - 如果您关心服务器交付而不是客户端中途取消。 IsClientConnected基于ASP.NET HttpResponse,而不是WebApi。