Funziona!
Ecco che cosa ho fatto:
Fase 1 & 2 - Azione Metodo viene chiamato, a lungo in esecuzione thread viene avviato
Quando il mio metodo di azione viene chiamato, genera un ID univoco. Quindi istanziare un'istanza della mia classe PdfGenerator
, creare un nuovo thread che chiama PdfGenerator.Generate
e avviarlo.
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 volta che il filo è iniziata (o prima) l'istanza generatore viene memorizzato nella cache:
HttpContext.Cache[guid] = generator;
Allego inoltre il GUID al Viewdata in modo che possa essere riferimento nella mia vista script.
Fase 3 & 4 - Display e vista
Ora che il thread è in esecuzione e la generazione di PDF ha iniziato aggiornamento di stato/di avanzamento, posso visualizzare mio punto di vista il progresso script. Usando di $.getJSON
sono in grado di eseguire il polling un'azione separata per trovare lo stato della generazione 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);
}
Il mio script vista interpreta il JSON e visualizza le informazioni di avanzamento appropriata.
Fase 5 - lima Presente all'utente
Una volta che la generazione è stata completata, lo stato di generatori è impostato di conseguenza e quando jQuery riceve queste informazioni, si può sia mettere a disposizione un link, o direttamente inviare il file utilizzando javascripts location.href
.
Il metodo d'azione che imposta e restituisce il file viene semplicemente il generatore di fuori della cache e restituisce il byte allegato []
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");
}
}
Il mio mio lavoro effettivo devo stato più dettagliate come inizializzato , In esecuzione e completato. Così come una percentuale di progresso (espressa come decimale, 1.0 completa).
Quindi sì, spero che aiuti chiunque altro a provare a fare qualcosa di simile.
Ottima domanda ... bloccato nella stessa situazione! –