用ASP.NET MVC下载后如何删除文件?

时间:2010-01-11 12:17:13

标签: c# asp.net-mvc

我想在下载后立即删除文件,我该怎么办?我试图继承FilePathResult并覆盖WriteFile方法,我在

之后删除文件
HttpResponseBase.TransmitFile

被调用,但这会挂起应用程序。

用户下载后可以安全删除文件吗?

13 个答案:

答案 0 :(得分:33)

读入文件的字节,删除它,调用基本控制器的文件操作。

public class MyBaseController : Controller
{
    protected FileContentResult TemporaryFile(string fileName, string contentType, string fileDownloadName)
    {
        var bytes = System.IO.File.ReadAllBytes(fileName);
        System.IO.File.Delete(fileName);
        return File(bytes, contentType, fileDownloadName);
    }
}
顺便说一句,如果你处理非常大的文件,你可能会避免使用这种方法,而你却担心内存消耗。

答案 1 :(得分:31)

创建文件并保存。
Response.Flush()将所有数据发送到客户端 然后你可以删除临时文件。

这对我有用:

FileInfo newFile = new FileInfo(Server.MapPath(tmpFile));

//create file, and save it
//...

string attachment = string.Format("attachment; filename={0}", fileName);
Response.Clear();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = fileType;
Response.WriteFile(newFile.FullName);
Response.Flush();
newFile.Delete();
Response.End();

答案 2 :(得分:22)

以上答案对我有帮助,这就是我最终的结果:

public class DeleteFileAttribute : ActionFilterAttribute
{
  public override void OnResultExecuted(ResultExecutedContext filterContext)
  {
     filterContext.HttpContext.Response.Flush();
     var filePathResult = filterContext.Result as FilePathResult;
     if (filePathResult != null)
     {
        System.IO.File.Delete(filePathResult.FileName);
     }
  }
}

答案 3 :(得分:21)

您可以定期返回使用FileStreamResult打开的常规FileOptions.DeleteOnClose。文件流将由asp.net处理结果。这个答案不需要使用低级响应方法,这些方法可能会在某些情况下适得其反。此外,不会进行额外的工作,例如将文件整个加载到内存中。

var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
return File(
    fileStream: fs,
    contentType: System.Net.Mime.MediaTypeNames.Application.Octet,
    fileDownloadName: "File.abc");

这个答案是基于Alan West的回答和Thariq Nugrohotomo的评论。

答案 4 :(得分:14)

您可以使用OnActionExecuted方法为操作创建自定义actionfilter,然后在操作完成后删除该文件,例如

public class DeleteFileAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
        // Delete file 
    } 
} 

然后你的行动

[DeleteFileAttribute]
public FileContentResult GetFile(int id)
{
   ...
}

答案 5 :(得分:6)

我在WebAPI中执行了相同的操作。我需要在下载表单服务器之后删除文件。 我们可以创建自定义响应消息类。它将文件路径作为参数,并在传输后将其删除。

 public class FileHttpResponseMessage : HttpResponseMessage
    {
        private readonly string filePath;

        public FileHttpResponseMessage(string filePath)
        {
            this.filePath = filePath;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            File.Delete(filePath);
        }
    }

将此类用作以下代码,一旦将其写入响应流,它将删除您的文件。

var response = new FileHttpResponseMessage(filePath);
            response.StatusCode = HttpStatusCode.OK;
            response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = "MyReport.pdf"
            };
            return response;

答案 6 :(得分:4)

覆盖OnResultExecuted方法可能是正确的解决方案..此方法在写入响应后运行。

public class DeleteFileAttribute : ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
        filterContext.HttpContext.Response.Flush();
        // Delete file 
    } 
} 

行动代码:

[DeleteFileAttribute]
public FileContentResult GetFile(int id)
{
   //your action code
}

答案 7 :(得分:2)

试试这个。这将正常工作。

public class DeleteFileAttribute : ActionFilterAttribute
{
  public override void OnResultExecuted( ResultExecutedContext filterContext )
  {
    filterContext.HttpContext.Response.Flush();
    string filePath = ( filterContext.Result as FilePathResult ).FileName;
    File.Delete( filePath );
  }
}

答案 8 :(得分:1)

我用过的模式。

1)创建文件。

2)删除旧的创建文件,FileInfo.CreationTime< DateTime.Now.AddHour(-1)

3)用户已下载。

这个想法怎么样?

答案 9 :(得分:1)

解决方案:

应该对FileResult进行子类化或创建自定义操作过滤器,但棘手的部分是在尝试删除文件之前刷新响应。

答案 10 :(得分:1)

以下是基于@biesiad for ASP.NET MVC(https://stackoverflow.com/a/4488411/1726296

的优雅解决方案的更新答案

基本上它会在发送响应后返回EmptyResult。

public ActionResult GetFile()
{
    string theFilename = "<Full path your file name>"; //Your actual file name
        Response.Clear();
        Response.AddHeader("content-disposition", "attachment; filename=<file name to be shown as download>"); //optional if you want forced download
        Response.ContentType = "application/octet-stream"; //Appropriate content type based of file type
        Response.WriteFile(theFilename); //Write file to response
        Response.Flush(); //Flush contents
        Response.End(); //Complete the response
        System.IO.File.Delete(theFilename); //Delete your local file

        return new EmptyResult(); //return empty action result
}

答案 11 :(得分:0)

我更喜欢返回HttpResponseMessage的解决方案。我喜欢Risord回答的简单性,因此我以相同的方式创建了一个流。然后,我将File属性设置为HttpResponseMessage.Content对象,而不是返回StreamContent

var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
return new HttpResponseMessage()
{
    Content = new StreamContent(fs)
};

答案 12 :(得分:-1)

我已在https://stackoverflow.com/a/43561635/1726296

中发布此解决方案
public ActionResult GetFile()
    {
            string theFilename = "<Full path your file name>"; //Your actual file name
            Response.Clear();
            Response.AddHeader("content-disposition", "attachment; filename=<file name to be shown as download>"); //optional if you want forced download
            Response.ContentType = "application/octet-stream"; //Appropriate content type based of file type
            Response.WriteFile(theFilename); //Write file to response
            Response.Flush(); //Flush contents
            Response.End(); //Complete the response
            System.IO.File.Delete(theFilename); //Delete your local file

            return new EmptyResult(); //return empty action result
    }