2009-08-24 27 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表示完整)。

所以是的,希望能帮助其他人尝试做类似的事情。

相关问题