Завершенное событие для 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()
{
//
}
5 ответов
Вы можете попробовать использовать пользовательский 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).
Существует готовое решение для jQuery, проверьте это http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/
Идея довольно проста: на стороне сервера вы создаете атрибут, который устанавливает пользовательский файл cookie после выполненного действия, на стороне клиента вы используете setTimeout, чтобы проверить этот файл cookie и сделать что-нибудь, когда он появится.
Клиент (браузер) выполняет загрузку, вы сервер не проинформированы, когда это будет сделано. С HTTP вы не можете сказать клиенту сделать что-то еще после загрузки.
Обычно вам нужны две темы, одна для загрузки и одна для уведомления. На стороне сервера эти потоки делятся информацией о том, сколько байтов от длины файла было отправлено. Поток загрузки выполняется через IHttpHandler, где вы анализируете http-запрос и записываете байты в буфер ответа http по буферу и обновляете общую информацию с помощью потока уведомлений. Поток уведомлений - это некоторый повторяющийся ajax-запрос со страницы, с которой вы начали скачивать. Вы также можете визуализировать прогресс загрузки с помощью jquery.