Asp.net-Mvc

將返回文件的長時間執行的程序

  • July 2, 2021

我正在使用 ASP.NET MVC 並且有一個長時間執行的過程。具體來說,我正在生成一個大的 PDF 供使用者下載。

我了解基本概念:

  1. 動作方法被呼叫
  2. 新執行緒開始生成程序
  3. 返回一個告訴使用者正在生成(pdf)的視圖
  4. 使用AJAX呼叫伺服器並詢問進度
  5. 完成後,將文件呈現給使用者以供下載。

我不完全理解的部分是:

  • 跨單獨 AJAX 呼叫的執行緒管理。我可能需要某種方法來查找正在執行的執行緒並請求狀態。是否有一個靜態上下文我可以保留對執行緒的引用?我知道中的數據記憶體HttpContext.Application,這適合這個嗎?
  • 以及如何呈現完成的文件。我是否創建一個臨時文件並提供下載連結?或者我可以進行最終的 AJAX 呼叫來返回文件嗎?

Cashe 非常適合這種情況。只有一件事是確保在程序執行時永遠不會刪除記憶體的項目(您可以使用 ItemPriority.NotRemovable )。

您可以將文件保存在磁碟上的臨時文件夾中,也可以將其保存在記憶體中一段時間(視情況而定)。

我個人不喜歡用文件污染硬碟,所以我會將文件保存在記憶體中(使用 MediumPriority 幾分鐘)。但是如果文件很大並且可以生成,通常考慮使用文件系統的數據庫。

在客戶端,當最後一個 Ajax 請求返回 result( 可能看起來像*{progress: “100%”, resultUrl: “http://your.url/Where/ToGet/TheFile.aspx?file=GUID-OR-CACHE- KEY”}* ) 您可以將瀏覽器重定向到提供的 URL。

反過來,它將將該文件呈現為二進制結果。

客戶端重定向可以使用 Javascript 來完成,如下所示:

location.href = response.resultUrl;

順便說一句,你如何生成 PDF?非政府組織?

有用!

這是我所做的:

第 1 步和第 2 步 - 呼叫 Action 方法,啟動長時間執行的執行緒

當我的操作方法被呼叫時,它會生成一個唯一的 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

設置並返回文件的 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");
   }
}

在我的實際工作中,我得到了更詳細的狀態,例如 Initialized、Running 和 Completed。以及進度百分比(以小數表示,1.0 表示完整)。

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

引用自:https://stackoverflow.com/questions/1325054