【问题标题】:ActionResultFilter page not found errorActionResultFilter 页面未找到错误
【发布时间】:2013-06-05 14:37:12
【问题描述】:

我正在使用 .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”局部变量。但我不知道如何将该值传递给这个事件。

【问题讨论】:

  • 感谢更正,使其更具可读性。
  • 而PageNotFound是filter造成的(即没有它下载就OK了)?
  • 没有进行下载。
  • 没有人知道这个话题吗? :(我卡在这里..
  • 您可以使用调试器或通过记录来验证文件名部分。我们的细节太少,无法理解路由错误。

标签: c# asp.net-mvc-3 actionfilterattribute


【解决方案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);
    }

【讨论】:

  • 谢谢,如果围绕 File.Delete 方法检查文件是否忙怎么办?如果在将文件发送到客户端期间文件在服务器端保持忙碌,我想我的方法会起作用,否则定期清理它们仍然是一个问题,因为我不知道文件是否仍在下载。等到需要下载新文件也不是一个好方法,因为它会使我的服务器超载。因为需要下载的文件可能在 2-3 GB 左右。我不想存储它们。
  • 再次感谢,我猜这个flush方法让它等到下载完成,对吧?
  • 是的,您可能需要留意超时问题。
  • 非常感谢您的帮助。我应该怎么做才能绕过找不到页面的错误?如果你也能帮我解决这个问题,我将不胜感激。
  • 我不知道。尝试追踪它并更好地记录它(路线等)。然后可能会发布一个新的单独问题。
猜你喜欢
  • 2015-06-22
  • 2012-09-15
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-17
  • 2016-01-18
相关资源
最近更新 更多