简体   繁体   English

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

[英]How to delete file after download with ASP.NET MVC?

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? 用户下载后可以安全删除文件吗?

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. 顺便说一句,如果你处理非常大的文件,你可能会避免使用这种方法,而你却担心内存消耗。

Create file and save it. 创建文件并保存。
Response.Flush() sends all data to client. Response.Flush()将所有数据发送到客户端。
Then you can delete temporary file. 然后你可以删除临时文件。

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

You can return just regular FileStreamResult which is opened with FileOptions.DeleteOnClose . 您可以返回使用FileOptions.DeleteOnClose打开的常规FileStreamResult File stream will be disposed with result by asp.net. 文件流将由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. 此外,不会进行额外的工作,例如将文件整体加载到内存中。

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的评论。

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

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)
{
   ...
}

I performed same action in WebAPI. 我在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. 它将文件路径作为参数,并在传输后将其删除。

 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;

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
}

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

My used pattern. 我使用的模式。

1)Create file. 1)创建文件。

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

3)User downloaded. 3)用户下载。

How about this idea? 这个想法怎么样?

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的子类或创建自定义操作过滤器,但棘手的部分是在尝试删除文件之前刷新响应。

Here is updated answer based on elegant solution by @biesiad for ASP.NET MVC ( https://stackoverflow.com/a/4488411/1726296 ) 以下是基于@biesiad for ASP.NET MVC优雅解决方案的更新答案( https://stackoverflow.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
}

I preferred a solution which returned an HttpResponseMessage . 我更喜欢一个返回HttpResponseMessage的解决方案。 I liked the simplicity of Risord's answer, so I created a stream in the same manner. 我喜欢Risord答案的简单性,所以我以同样的方式创建了一个流。 Then, instead of returning a File , I set the HttpResponseMessage.Content property to a StreamContent object. 然后,我将HttpResponseMessage.Content属性设置为StreamContent对象,而不是返回File

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

I have posted this solution in https://stackoverflow.com/a/43561635/1726296 我已在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
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM