15

I want to do something after user finishes downloading

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

What I tried is to add the following events to test controller but they all fires before user finish downloading (except destructor it never gets called)

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()
{
    //
}
Almis
  • 3,684
  • 2
  • 28
  • 58

5 Answers5

3

There is ready-made solution for jQuery, check this out http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
The idea is pretty simple: on server-side you create attribute which sets custom cookie after action executed, on client-side you use setTimeout to check this cookie and do something when it'll come.

HollyDolly
  • 39
  • 1
  • 1
    I wouldn't recommend using cookies for anything anymore. (unless dipped in your favorite beverage). – ericosg Sep 11 '15 at 06:23
  • I'm very grateful for argumentative comment. Of course, you can use different ways to check some info from server, but this is the fastest/simplest in this case – HollyDolly Sep 11 '15 at 10:49
3

You can try to use custom FileStreamResult as described here - 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;
}

As you see, WriteFile method is overriden and custom logic is implemented to serve response.OutputStream to client by reading chunks from FileStream and writing to OutputStream. At the end of this process you may consider file downloaded. Then you can check DownloadCompleted in OnResultExecuted handler of controller. Alternatively, you can try pass custom Action delegate to CheckedFileStreamResult constructor and invoke that when download completes (instead of using DownloadCompleted flag).

Evk
  • 98,527
  • 8
  • 141
  • 191
0

The client (a browser) is doing the downloading, you the server are not informed when it is done. With HTTP you cannot tell the client to do something else after downloading.

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
  • I don't want to tell him to do something else. The server sending the stream so it should know when it finished. – Almis Sep 02 '15 at 10:09
0

If you want to do something on server, may be you can use PushStreamContent. Here is stackoverflow answer and a blog entry.

Community
  • 1
  • 1
0

Generally you need two threads, one for downloading and one for notification. On the server side these threads share the info about how many bytes from file length was sent. The downloading thread is made via IHttpHandler, where you parse the http query and write bytes to http response buffer by buffer and updates the shared information with notification thread. The notification thread is some repeating ajax query from the page where did you started downloading. You can also render the downloading progressbar with jquery.

Tomas Kubes
  • 23,880
  • 18
  • 111
  • 148