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

时间:2022-03-30 15:17:41

I want to delete a file immediately after download, how do I do it? I've tried to subclass FilePathResult and override the WriteFile method where I delete file after

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

HttpResponseBase.TransmitFile

is called, but this hangs the application.

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

Can I safely delete a file after user downloads it?

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

12 个解决方案

#1


13  

You could create a custom actionfilter for the action with an OnActionExecuted Method that would then remove the file after the action was completed, something like

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

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

then your action has

然后你的行动了

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

#2


29  

Read in the bytes of the file, delete it, call the base controller's File action.

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

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

BTW, you may refrain from this method if you're dealing with very large files, and you're concerned about the memory consumption.

顺便说一下,如果你处理的是非常大的文件,你可能会避免使用这种方法,而你却担心内存消耗。

#3


27  

Create file and save it.
Response.Flush() sends all data to client.
Then you can delete temporary file.

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

This works for me:

这对我有用:

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

#4


19  

Above answers helped me, this is what I ended up with:

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

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

#5


11  

You can return just regular FileStreamResult which is opened with FileOptions.DeleteOnClose. File stream will be disposed with result by asp.net. This answer dosen't require usage of low level response methods which may backfire in certain situations. Also no extra work will be done like loading file to memory as whole.

您可以返回使用FileOptions.DeleteOnClose打开的常规FileStreamResult。文件流将由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");

This answer is based on answer by Alan West and comment by Thariq Nugrohotomo.

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

#6


6  

I performed same action in WebAPI. I needed to delete file just after it downloaded form server. We can create custom response message class. It takes file path as parameter and delete it once its transmitted.

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

Use this class as below code and it will delete your file once it will be written on response stream.

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

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;

#7


4  

overriding the OnResultExecuted method is probably the correct solution.. This method runs after the response is written.

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

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

Action code:

行动代码:

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

#8


2  

Try This. This will work properly.

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

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

#9


1  

My used pattern.

我使用的模式。

1)Create file.

1)创建文件。

2)Delete old created file, FileInfo.CreationTime < DateTime.Now.AddHour(-1)

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

3)User downloaded.

3)用户下载。

How about this idea?

这个想法怎么样?

#10


1  

SOLUTION:

解:

One should either subclass the FileResult or create a custom action filter, but the tricky part is to flush the response before trying to delete the file.

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

#11


0  

Here is updated answer based on elegant solution by @biesiad for ASP.NET MVC ( https://*.com/a/4488411/1726296)

以下是@biesiad针对ASP.NET MVC的优雅解决方案的更新答案(https://*.com/a/4488411/1726296)

Basically it returns EmptyResult after response is sent.

基本上它在发送响应后返回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
}

#12


-1  

I have posted this solution in https://*.com/a/43561635/1726296

我已在https://*.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
    }

#1


13  

You could create a custom actionfilter for the action with an OnActionExecuted Method that would then remove the file after the action was completed, something like

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

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

then your action has

然后你的行动了

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

#2


29  

Read in the bytes of the file, delete it, call the base controller's File action.

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

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

BTW, you may refrain from this method if you're dealing with very large files, and you're concerned about the memory consumption.

顺便说一下,如果你处理的是非常大的文件,你可能会避免使用这种方法,而你却担心内存消耗。

#3


27  

Create file and save it.
Response.Flush() sends all data to client.
Then you can delete temporary file.

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

This works for me:

这对我有用:

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

#4


19  

Above answers helped me, this is what I ended up with:

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

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

#5


11  

You can return just regular FileStreamResult which is opened with FileOptions.DeleteOnClose. File stream will be disposed with result by asp.net. This answer dosen't require usage of low level response methods which may backfire in certain situations. Also no extra work will be done like loading file to memory as whole.

您可以返回使用FileOptions.DeleteOnClose打开的常规FileStreamResult。文件流将由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");

This answer is based on answer by Alan West and comment by Thariq Nugrohotomo.

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

#6


6  

I performed same action in WebAPI. I needed to delete file just after it downloaded form server. We can create custom response message class. It takes file path as parameter and delete it once its transmitted.

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

Use this class as below code and it will delete your file once it will be written on response stream.

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

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;

#7


4  

overriding the OnResultExecuted method is probably the correct solution.. This method runs after the response is written.

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

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

Action code:

行动代码:

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

#8


2  

Try This. This will work properly.

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

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

#9


1  

My used pattern.

我使用的模式。

1)Create file.

1)创建文件。

2)Delete old created file, FileInfo.CreationTime < DateTime.Now.AddHour(-1)

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

3)User downloaded.

3)用户下载。

How about this idea?

这个想法怎么样?

#10


1  

SOLUTION:

解:

One should either subclass the FileResult or create a custom action filter, but the tricky part is to flush the response before trying to delete the file.

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

#11


0  

Here is updated answer based on elegant solution by @biesiad for ASP.NET MVC ( https://*.com/a/4488411/1726296)

以下是@biesiad针对ASP.NET MVC的优雅解决方案的更新答案(https://*.com/a/4488411/1726296)

Basically it returns EmptyResult after response is sent.

基本上它在发送响应后返回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
}

#12


-1  

I have posted this solution in https://*.com/a/43561635/1726296

我已在https://*.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
    }