我正在使用.NET MVC3开发一个网站。我有一个控制器,我将文件下载到客户端。
[DeleteFileAfterDownloadFilter()]
public FileResult DownloadVersion(int VersionID)
{
//staff to get the tempZipFile
return File(tempZipFile, "zip", "file.zip");
}
我喜欢的是在下载此文件后删除该文件。我想我可以使用ActionFilterAttribute
。所以我写了下面的课程:
public class DeleteFileAfterDownloadFilter : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
string fileName = ((FileStreamResult)filterContext.Result).FileDownloadName;
File.Delete(fileName);
base.OnResultExecuted(filterContext);
}
}
我想这里有2个问题。
第一个是当我运行这个东西时它给了我".../Company/DownloadVersion?versionID=2057"
页面的错误找不到。是什么方法让它发挥作用?
第二个问题是,您可能已经意识到"((FileStreamResult)filterContext.Result).FileDownloadName"
可能不是我要删除的文件路径。它应该是控制器中的“tempZipFile”局部变量。但我不知道如何将这个值传递给这个事件。
答案 0 :(得分:1)
我给你的过滤器一个旋转和(校正后)它产生一个令人讨厌的COM错误。
这是因为操作的异步性质:OnResultExecuted
是你做某事的最后机会,但是当响应(带有文件名但不是文件本身)已经发送回客户端时会发生这种情况。当客户端(浏览器)然后开始下载时,会发生Not Found错误或更糟。
换句话说,你的方法看起来很不错但不起作用。
解决方案的一些粗略想法:
我改变了你的过滤器:
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
var r = filterContext.Result as FilePathResult; // not FileContent
string fileName =
filterContext.RequestContext.HttpContext.Server.MapPath(r.FileName);
System.IO.File.Delete(fileName);
}
更新:
感谢this SO answer,以下内容应该有效:
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
var r = filterContext.Result as FilePathResult; // not FileContent
string fileName =
filterContext.RequestContext.HttpContext.Server.MapPath(r.FileName);
filterContext.HttpContext.Response.Flush();
filterContext.HttpContext.Response.End();
System.IO.File.Delete(fileName);
}