长时间运行的进程将返回一个文件

jee*_*ef3 8 asp.net-mvc

我正在使用ASP.NET MVC并且运行时间很长.具体来说,我正在生成一个大PDF供用户下载.

我理解基本概念:

  1. 调用Action方法
  2. 新线程开始生成进程
  3. 返回一个视图,告诉用户正在生成(pdf)
  4. 使用AJAX调用服务器并要求进度
  5. 完成后,将文件呈现给用户以供下载.

我不完全理解的部分是:

  • 跨越单独的AJAX调用管理线程.我可能需要一些方法来查找正在运行的线程并请求状态.是否有静态上下文我可以保持对线程的引用?我知道数据缓存HttpContext.Application,这适合这个吗?
  • 以及如何呈现已完成的文件.我是否创建临时文件并提供下载链接?或者我可以进行返回文件的最终AJAX调用吗?

jee*_*ef3 7

有用!

这就是我所做的:

步骤1和2 - 调用Action Method,启动长时间运行的线程

当我的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[]
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦线程启动(或在启动之前),生成器实例就存储在缓存中:

HttpContext.Cache[guid] = generator;
Run Code Online (Sandbox Code Playgroud)

我还将guid附加到ViewData,以便它可以在我的视图脚本中引用.

步骤3和4 - 显示和更新状态/进度视图

现在线程正在运行并且PDF生成已经开始,我可以显示我的进度视图脚本.使用jQuery $.getJSON我可以轮询一个单独的Action来查找生成的状态:

[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);
}
Run Code Online (Sandbox Code Playgroud)

我的视图脚本解释Json并显示适当的进度信息.

第5步 - 向用户显示文件

生成完成后,将相应地设置生成器状态,当jQuery收到此信息时,它可以提供链接,也可以使用javascripts直接发送文件location.href.

设置并返回文件的Action方法只是将生成器从缓存中取出并返回附加的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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的实际工作我有更详细的状态,如Initialised,Running和Completed.以及进度百分比(以小数表示,1.0表示完整).

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


Dmy*_*iak 6

Cashe非常适合这种情况.只有一件事是确保在进程运行时永远不会删除缓存的项目(您可以使用ItemPriority.NotRemovable).

您可以将文件保存在临时文件夹中的磁盘上,也可以将其保留在缓存中一段时间​​(取决于).
我个人不喜欢用文件污染硬盘,所以我会将文件保存在缓存中(在几分钟内使用MediumPriority).但是文件很大并且可以生成经常考虑使用文件系统的数据库.

在客户端上,当最后一个Ajax请求返回结果时(看起来像{progress:"100%",resultUrl:" http://your.url/Where/ToGet/TheFile.aspx?file = GUID-OR-CACHE- KEY "})您可以将浏览器重定向到提供的网址.
反过来,它将该文件呈现为二进制结果.

客户端重定向可以使用以下Javascript完成:

location.href = response.resultUrl;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你如何生成PDF?NFOP?