2

我正在使用 .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);
    }
}

我想我在这里有两个问题。第一个是,当我运行这个东西时,它给了我".../Company/DownloadVersion?versionID=2057"找不到页面的错误。使它工作的方法是什么?

第二个问题是您可能已经意识到"((FileStreamResult)filterContext.Result).FileDownloadName"可能不是我要删除的文件路径。它应该是控制器中的“tempZipFile”局部变量。但我不知道如何将该值传递给这个事件。

4

1 回答 1

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);
    }

更新 :

感谢这个 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);
    }
于 2013-06-06T13:21:08.703 回答