Завершено событие для FilePathResult

Я хочу что-то сделать после завершения загрузки пользователем

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()
{
    //
}

Ответы

Ответ 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 переопределяется, и пользовательская логика реализована для обслуживания response.OutputStream для клиента путем чтения фрагментов из FileStream и записи в OutputStream. В конце этого процесса вы можете рассмотреть файл, загруженный. Затем вы можете проверить DownloadCompleted в обработчике OnResultExecuted контроллера. Кроме того, вы можете попробовать передать пользовательский делегат Action в конструктор CheckedFileStreamResult и вызвать его при завершении загрузки (вместо использования флажка DownloadCompleted).

Ответ 2

Есть готовое решение для jQuery, проверьте это http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
Идея довольно проста: на стороне сервера вы создаете атрибут, который устанавливает пользовательский cookie после выполнения действия, на стороне клиента вы используете setTimeout, чтобы проверить этот файл cookie и сделать что-то, когда оно придет.

Ответ 3

Клиент (браузер) выполняет загрузку, сервер не информируется, когда это делается. С помощью HTTP вы не можете сказать клиенту сделать что-то еще после загрузки.

Ответ 4

Если вы хотите что-то сделать на сервере, возможно, вы можете использовать PushStreamContent. Здесь есть ответ stackoverflow и запись в блоге.

Ответ 5

Как правило, вам нужны два потока: один для загрузки и один для уведомления. На стороне сервера эти потоки разделяют информацию о том, сколько байтов от длины файла было отправлено. Загружаемый поток создается через IHttpHandler, где вы анализируете HTTP-запрос и записываете байты в буфер HTTP-ответа буфером и обновляете общую информацию с помощью потока уведомлений. Поток уведомлений представляет собой некоторый повторяющийся запрос ajax со страницы, на которой вы начали загрузку. Вы также можете отобразить панель выполнения загрузки с помощью jquery.