¡Funciona!
Esto es lo que he hecho:
& Paso 1 2 - Método de Acción se llama, de larga duración hilo se inicia
Cuando mi método de acción es llamado, se genera un identificador único. A continuación, instalo una instancia de mi clase PdfGenerator
, creo un nuevo hilo que llame al PdfGenerator.Generate
y lo inicie.
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[]
}
}
Una vez que el mensaje ha comenzado (o antes de empezar) la instancia del generador se almacena en la memoria caché:
HttpContext.Cache[guid] = generator;
también hay que adjuntar el GUID a la ViewData de modo que pueda ser referencia en mi opinión guión.
Paso 3 & 4 - Visualización y actualización de estado/progreso vista
Ahora que el hilo se está ejecutando y la generación de PDF ha comenzado, puedo mostrar mi punto de vista el progreso de la escritura. El uso de $.getJSON
soy capaz de sondear una acción separada para encontrar el estado de la generación de jQuery:
[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);
}
Mi script de vista interpreta el JSON y muestra la información de progreso adecuado.
Paso 5 - archivo actual de usuario
Una vez que se ha completado la generación, el estado generadoras se fija en consecuencia y cuando jQuery recibe esta información, o bien puede hacer un enlace disponible, o directamente enviar el archivo usando javascripts location.href
.
el método de acción que establece y devuelve el archivo, simplemente se pone el generador fuera de la caché y devuelve el byte adjunto []
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");
}
}
Mi mi trabajo real tengo estado más detallada, como inicializado , Corriendo y Completado. Además de un porcentaje de progreso (expresado como un decimal, 1.0 está completo).
Así que sí, espero que ayude a alguien más a tratar de hacer algo similar.
Excelente pregunta ... atrapado en la misma situación! –