我正在使用ASP.NET MVC并且运行时间很长。具体来说,我正在生成一个大PDF供用户下载。
我理解基本概念:
我不完全理解的部分是:
HttpContext.Application
中的数据缓存,是否适用于此?答案 0 :(得分: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[]
}
}
线程启动后(或启动前),生成器实例存储在缓存中:
HttpContext.Cache[guid] = generator;
我还将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);
}
我的视图脚本解释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");
}
}
我的实际工作我有更详细的状态,例如Initialised,Running和Completed。除了进度百分比(以小数表示,1.0表示完整)。
所以是的,希望能帮助其他人尝试做类似的事情。
答案 1 :(得分: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;
顺便说一句,你如何生成PDF? NFOP?