我有一个使用外部进程创建文件的类,并将其作为下载结果返回,此时我想从服务器中删除该文件。我通常喜欢避免临时的磁盘文件,但在这种情况下,它是不可避免的。
我最初尝试使用Dispose方法实现它:
public class SetupFile : IDisposable
{
/// <summary>Local file path</summary>
public string LocalFilePath { get; set; }
/// <summary>Filename to present to user</summary>
public string DownloadFilename { get; set; }
public void Dispose()
{
System.IO.File.Delete(LocalFile);
}
}
控制器代码创建并操作此文件,然后将结果作为FilePathResult
:
public class DownloadController : Controller
{
public SetupFileGenerator Generator { get; set; }
public DigitalSignatureTool Signer { get; set; }
[HttpPost, Route("/download")]
public ActionResult Download(InstallParams params)
{
using (SetupFile file = Generator.Generate(params)) {
{
Signer.Sign(file.LocalFilePath); // note: requires a local path!
return new FilePathResult(file.LocalFilePath, "application/octet-stream")
{
FileDownloadName = file.DownloadFilename
};
}
}
}
(请注意,Generator
和Signer
正通过依赖注入插入到Controller中,为了保持关注点的分离,我不希望SetupFileGenerator
依赖DigitalSignatureTool
1}}。关于这一点的重要一点是,我确实需要磁盘上的文件才能运行Signer.Sign
- 因此Generator.Generate()
无法返回流。)
这里的问题是FilePathResult
仅在稍后在处理管道中调用its WriteFile()
method时发送文件,这意味着我的SetupFile.Dispose()
方法已被调用。
我认为我的下一步是做两件事之一:
FilePathResult
的新类,但在发送后删除该文件SetupFile
拥有属性string LocalFilePath
,而MemoryStream FileContents
然而,这似乎是一个相当常见的模式,所以在我重新发明轮子之前,是否有最佳实施方法?有什么需要特别注意的吗?
答案 0 :(得分:3)
OnResultExecuted方法在写入响应后运行。您可以使用ActionFilterAttribute覆盖它。
public class DeleteFileAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Flush();
string filePath = (filterContext.Result as FilePathResult).FileName;
System.IO.File.Delete(filePath);
}
}
按照以下方式装饰您的方法:
[DeleteFile]
[HttpPost, Route("/download")]
public ActionResult Download(InstallParams params)
{
using (SetupFile file = Generator.Generate(params))
{
Signer.Sign(file.LocalFilePath);
return new FilePathResult(file.LocalFilePath, "application/octet-stream")
{
FileDownloadName = file.DownloadFilename
};
}
}