2009-08-24 6 views
8

Ich benutze ASP.NET MVC und habe einen langen laufenden Prozess. Speziell erzeuge ich ein großes PDF für den Benutzer zum Download.Langer Prozess, der eine Datei zurückgibt

Ich verstehe das Grundkonzept:

  1. Aktion Methode
  2. New Thread aufgerufen wird gestartet Prozess wird
  3. Zurück zu generieren eine Ansicht, die den Benutzer sagt das (pdf)
  4. Verwendung erzeugt wird AJAX, um den Server anzurufen und nach dem Fortschritt zu fragen
  5. Wenn Sie fertig sind, legen Sie die Datei dem Benutzer zum Herunterladen bereit.

Die Teile ich nicht ganz verstehen sind:

  • Das Management des Themas auf getrennte AJAX aufruft. Ich werde möglicherweise eine Möglichkeit brauchen, den laufenden Thread zu finden und einen Status anzufordern. Gibt es einen statischen Kontext, in dem ich einen Verweis auf den Thread beibehalten kann? Ich bin mir des Data Caching in HttpContext.Application bewusst, wäre das dafür geeignet?
  • Und wie die fertige Datei zu präsentieren. Erstelle ich eine temporäre Datei und präsentiere einen Download-Link? Oder kann ich einen abschließenden AJAX-Aufruf durchführen, der die Datei zurückgibt?
+0

Ausgezeichnete Frage ... in derselben Situation stecken! –

Antwort

6

Das Cashe ist sehr gut dafür geeignet. Es ist nur eine Sache, sicherzustellen, dass das zwischengespeicherte Objekt niemals entfernt wird, während der Prozess läuft (Sie können dafür ItemPriority.NotRemovable verwenden).

Sie können die Datei auf der Festplatte im temporären Ordner speichern oder sie für einige Zeit im Cache behalten (abhängig davon).
Ich persönlich möchte nicht die Festplatte mit Dateien verschmutzen, so dass ich die Datei im Cache behalten würde (mit MediumPriority während ein paar Minuten). Aber von der Datei ist groß und kann oft mit der Datenbank des Dateisystems erstellt werden.

auf dem Client, wenn der letzte kehrt Ajax-Request führt (wie aussehen kann {Fortschritt: "100%", resultUrl: "http://your.url/Where/ToGet/TheFile.aspx?file=GUID-OR-CACHE-KEY"}) Sie können zur Verfügung gestellt Browser auf eine URL umleiten.
Es wiederum wird diese Datei als binäres Ergebnis rendern.

Client-Umleitung kann mit Javascript wie folgt erfolgen:

location.href = response.resultUrl; 

BTW, wie Sie PDF generieren tun? NFOP?

+0

Danke für die Antwort. Ich werde es in Kürze versuchen, damit du weißt, wie es mir geht. Im Moment habe ich keine Mittel für die eigentliche PDF Erzeugung :( – jeef3

+0

Eine andere Sache, die ich vergaß zu erwähnen. Es gibt AsynController auf der ASP.NET MVC CodePlex-Website. Es könnte Ihnen nützlich sein. Ich denke, es aus dem Einfädeln abstrahiert Aufgaben. –

+0

Oh wow, interessant, werden in dem suchen. – jeef3

7

Es funktioniert!

Hier ist, was ich getan habe:

Schritt 1 & 2 - Action-Methode aufgerufen wird, langen Faden gestartet wird

Als meine Aktion-Methode aufgerufen wird, es eine eindeutige ID generiert. Ich instanziiere dann eine Instanz meiner PdfGenerator Klasse, erstelle einen neuen Thread, deraufruft und starte ihn.

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[] 
    } 
} 

Sobald der Thread gestartet (oder vor dem Start) der Generator beispielsweise in dem Cache gespeichert ist:

HttpContext.Cache[guid] = generator; 

I die den Viewdata guid auch befestigen, so daß sie Bezug meiner Ansicht sein können, Skript.

Schritt 3 & 4 - Anzeige und Update-Status/Fortschritt Ansicht

Nun, da der Thread ausgeführt wird und PDF-Generierung hat, ich begonnen meine Fortschritte View Skript anzuzeigen. Mit jQuery $.getJSON Ich bin in der Lage eine separate Aktion abfragen, den Status der Generation zu finden:

[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); 
} 

Meine Ansicht Skript die Json interpretiert und zeigt die entsprechenden Fortschrittsinformationen.

Schritt 5 - Geschenk-Datei Benutzer

Sobald die Generation abgeschlossen ist, wird die Generatoren Zustand entsprechend eingestellt und wenn jQuery diese Information erhält, kann es entweder zur Verfügung stellt einen Link oder die Datei direkt senden mit Javascripts location.href.

Die Aktion Methode, die die Datei einfach einrichtet und gibt den Generator aus dem Cache wird und gibt das angeschlossene byte []

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"); 
    } 
} 

ich meine meine eigentliche Arbeit detaillierteren Zustand haben wie Initialised , Ausgeführt und abgeschlossen. Sowie ein Fortschrittsprozentsatz (ausgedrückt als Dezimalzahl, wobei 1,0 vollständig ist).

Also ja, hoffen, dass jemand versucht, hilft etwas Ähnliches zu tun.

Verwandte Themen