2009-08-24 32 views
8

我正在使用ASP.NET MVC並有一個長時間運行的進程。具體來說,我正在生成一個大的PDF供用戶下載。長時間運行的進程將返回一個文件

我理解的基本概念:

  1. 操作方法被調用
  2. 新線程開始生成過程
  3. 返回查看,告訴用戶(PDF),正在生成
  4. 使用AJAX調用服務器並詢問進度
  5. 完成後,將文件呈現給用戶進行下載。

我不完全理解的部分是:

  • 線程的跨越單獨的AJAX調用管理。我可能需要一些方法來查找正在運行的線程並請求狀態。有沒有靜態的上下文我可以保持對線程的引用?我知道HttpContext.Application中的數據緩存,是否適合此?
  • 以及如何呈現完成的文件。我是否創建臨時文件並提供下載鏈接?或者我可以做一個最終的AJAX調用返回文件?
+0

優秀的問題...堅持在相同的情況! –

回答

6

卡西非常適合這一點。只有一件事是確保緩存項在進程運行時永遠不會被刪除(您可以使用ItemPriority.NotRemovable)。

您可以將文件保存在臨時文件夾中的磁盤上,或者您可以將其保存在緩存中一段時間​​(具體取決於)。
我個人不喜歡用文件污染硬盤,所以我會將文件保存在緩存中(在幾分鐘內使用MediumPriority)。但是文件的大而且可以經常考慮使用文件系統的數據庫來生成。

在客戶端,當最後一個Ajax請求返回結果(可以像{進步:「100%」,resultUrl:「http://your.url/Where/ToGet/TheFile.aspx?file=GUID-OR-CACHE-KEY」}),你可以重定向瀏覽器提供了一個網址。
反過來,將呈現該文件作爲二進制結果。

location.href = response.resultUrl; 

BTW,你如何生成PDF:

重定向客戶可以使用JavaScript這樣做呢? NFOP?

+0

感謝您的回答。我很快就會試試這個,所以會讓你知道我如何繼續。 目前我沒有辦法生成實際的PDF:( – jeef3

+0

另一件我忘了提及的東西。在ASP.NET MVC CodePlex站點上有AsynController,它可能對你有用,我認爲它是從線程抽象出來的任務 –

+0

哦,哇,有趣的,將不得不看看。 – jeef3

7

它的工作原理!

這裏是我做了什麼:

步驟1 & 2 - 動作方法被調用,長期運行的線程啓動

當我的操作方法被調用,它會生成一個唯一的ID。然後我實例化一個我的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

指建立和返回文件只是獲取發電機從緩存中,並返回所附的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"); 
    } 
} 

我的我的實際工作中我有更詳細的狀態,如初始化操作方法,正在運行並完成。以及進度百分比(以小數表示,1.0表示完整)。

所以是的,希望能幫助其他人嘗試做類似的事情。

相關問題