Работает!
Вот что я сделал:
Шаг 1 и 2 - вызывается метод действия, запущен длительный поток
Когда вызывается мой метод действия, он генерирует уникальный идентификатор. Затем я создаю экземпляр моего класса PdfGenerator
, создаю новый поток с именем PdfGenerator.Generate
и запускаю его.
public class PdfGenerator
{
public string State;
public byte[] Data;
public void Generate()
{
// Generate PDF/Long running process
// Should update State as it goes
// ...
// Once finished, Data is populated with the binary byte[]
}
}
После запуска потока (или до его запуска) экземпляр генератора сохраняется в кеше:
HttpContext.Cache[guid] = generator;
Я также прикрепляю guid к ViewData, чтобы он мог быть ссылкой в моем скрипте вида.
Шаг 3 и 4 - Отображение и обновление статуса / просмотр хода выполнения
Теперь, когда поток запущен и началась генерация PDF, я могу отобразить свой сценарий просмотра прогресса. Используя jQuery $.getJSON
, я могу опросить отдельное действие, чтобы узнать статус генерации:
[OutputCache(Duration = 0, VaryByName = "none", NoStore = true)]
public JsonResult CheckPdfGenerationStatus(string guid)
{
// Get the generator from cache
var generator = HttpContext.Cache[guid] as PdfGenerator;
if (generator == null)
return Json(null);
else
return Json(generator.State);
}
Мой скрипт просмотра интерпретирует Json и отображает соответствующую информацию о прогрессе.
Шаг 5 - представить файл пользователю
Как только генерация завершена, состояние генераторов устанавливается соответствующим образом, и когда jQuery получает эту информацию, он может либо сделать доступной ссылку, либо напрямую отправить файл, используя javascripts location.href
.
Метод Action, который устанавливает и возвращает файл, просто извлекает генератор из кэша и возвращает присоединенный байт []
public ContentResult DownloadPdf(string guid)
{
var generator = HttpContext.Cache[guid] as PdfGenerator;
if (generator == null)
return Content("Error");
if (generator.State == "Completed")
{
return Content(generator.Data);
}
else
{
return Content("Not finished yet");
}
}
Моя настоящая работа У меня есть более подробное состояние, такое как Инициализировано, Работает и Завершено. А также процент выполнения (в десятичном виде, 1,0 завершено).
Так что, да, надеюсь, это поможет кому-то еще, пытающемуся сделать что-то подобное.