【问题标题】:Completed event for FilePathResultFilePathResult 的已完成事件
【发布时间】:2015-09-02 09:54:18
【问题描述】:

我想在用户下载完成后做一些事情

public class TestController : Controller
{
    public FilePathResult Index()
    {
        return File("path/to/file", "mime");
    }
}

我尝试将以下事件添加到测试控制器,但它们都在用户完成下载之前触发(除了它永远不会被调用的析构函数)

protected override void EndExecute(IAsyncResult asyncResult)
{
    base.EndExecute(asyncResult);
}
protected override void EndExecuteCore(IAsyncResult asyncResult)
{
    base.EndExecuteCore(asyncResult);
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    base.OnActionExecuted(filterContext);
}
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
    base.OnResultExecuted(filterContext);
}
protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);
}
~TestController()
{
    //
}

【问题讨论】:

    标签: c# asp.net-mvc controller fileresult


    【解决方案1】:

    您可以尝试使用此处所述的自定义 FileStreamResult - http://odetocode.com/blogs/scott/archive/2010/06/23/checking-client-download-success-with-asp-net-mvc.aspx

    public class CheckedFileStreamResult : FileStreamResult
    {
        public CheckedFileStreamResult(FileStream stream, string contentType)
            :base(stream, contentType)
        {
            DownloadCompleted = false;
        }
    
        public bool DownloadCompleted { get; set; }
    
        protected override void WriteFile(HttpResponseBase response)
        {
            var outputStream = response.OutputStream;
            using (FileStream)
            {
                var buffer = new byte[_bufferSize];
                var count = FileStream.Read(buffer, 0, _bufferSize);
                while(count != 0 && response.IsClientConnected)
                {                 
                    outputStream.Write(buffer, 0, count);
                    count = FileStream.Read(buffer, 0, _bufferSize);
                }
                DownloadCompleted = response.IsClientConnected;
            }
        }
    
        private const int _bufferSize = 0x1000;
    }
    

    如您所见,WriteFile 方法被覆盖并实现了自定义逻辑,通过从 FileStream 读取块并写入 OutputStream 来为客户端提供 response.OutputStream。在此过程结束时,您可能会考虑下载文件。然后您可以在控制器的 OnResultExecuted 处理程序中检查 DownloadCompleted。或者,您可以尝试将自定义 Action 委托传递给 CheckedFileStreamResult 构造函数,并在下载完成时调用它(而不是使用 DownloadCompleted 标志)。

    【讨论】:

      【解决方案2】:

      jQuery 有现成的解决方案,看看这个http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
      这个想法很简单:在服务器端创建属性,在执行操作后设置自定义 cookie,在客户端使用 setTimeout 来检查这个 cookie 并在它到来时做一些事情。

      【讨论】:

      • 我不会再推荐使用cookies了。 (除非蘸上你最喜欢的饮料)。
      • 我非常感谢有争议的评论。当然,您可以使用不同的方式从服务器检查一些信息,但在这种情况下这是最快/最简单的
      【解决方案3】:

      客户端(浏览器)正在下载,下载完成后服务器不会收到通知。使用 HTTP,您无法在下载后告诉客户端执行其他操作。

      【讨论】:

      • 我不想告诉他做别的事情。服务器发送流,因此它应该知道何时完成。
      【解决方案4】:

      如果你想在服务器上做点什么,也许你可以使用 PushStreamContent。 Here 是 stackoverflow 的答案和 blog entry

      【讨论】:

      • PushStreamContent 是否基于 SignalR?你能给我一些阅读的来源吗?我猜它依赖于 Headers.TransferEncodingChunked = true..
      • 你是对的。我错了,它不依赖于signalR。我删除了我的评论。
      • 谢谢。但是由于您删除了您的评论,我的评论看起来很孤单。
      【解决方案5】:

      一般你需要两个线程,一个用于下载,一个用于通知。在服务器端,这些线程共享有关已发送文件长度的字节数的信息。下载线程是通过 IHttpHandler 进行的,您可以在其中解析 http 查询并将字节逐个缓冲区写入 http 响应缓冲区,并使用通知线程更新共享信息。通知线程是来自您开始下载的页面的一些重复 ajax 查询。也可以用jquery渲染下载进度条。

      【讨论】:

        猜你喜欢
        • 2019-02-28
        • 1970-01-01
        • 1970-01-01
        • 2013-01-08
        • 2013-04-16
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        • 1970-01-01
        相关资源
        最近更新 更多