2010-01-11 102 views
22

我想在下載後立即刪除文件,我該怎麼做?我試着子類FilePathResult和覆蓋WriteFile方法,我如何使用ASP.NET MVC下載後刪除文件?

HttpResponseBase.TransmitFile 

被調用後刪除的文件,但是這將使應用程序掛起。

用戶下載後可以安全刪除文件嗎?

+0

解決方案應該在'答案'中,而不是在問題中。 – 2010-01-11 13:53:37

回答

11

您可以創建用於與OnActionExecuted法的行動,那麼這將是完成動作後刪除文件的自定義actionfilter,像

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

那麼你的動作有

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

下載暫停,永不完成,想法? – Valentin 2010-01-11 12:32:37

+0

當然,我沒有想到,您在下載完成之前刪除文件。你能否在每次請求新結果之前刪除以前生成的文件,這就是我在類似的聲音情況下所做的。 – Israfel 2010-01-11 12:34:49

+0

這是否提供解決方案 – Krunal 2010-01-11 12:38:19

1

我使用的模式。

1)創建文件。

2)刪除舊創建的文件,FileInfo.CreationTime < DateTime.Now.AddHour(-1)

3)用戶下載。

這個想法怎麼樣?

+0

請看我的回答,它現在真的有效 – Valentin 2010-01-11 14:52:21

1

SOLUTION:

你要麼子類FileResult或者創建自定義操作過濾器,但棘手的部分是刷新試圖刪除文件之前的響應。

27

創建文件並保存。
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(); 
+0

工作過,非常感謝! – wheelibin 2011-03-21 16:09:50

+0

它也適用於大文件(大於512 Mb)嗎? – vibs2006 2017-04-21 09:56:06

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 
} 
26

讀取該文件的字節,將其刪除,調用基控制器的文件操作。

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

順便說一句,如果您處理非常大的文件,並且您關心內存消耗,您可以不要這種方法。

+0

你確定這是這個問題的有效答案嗎? – Oerd 2013-02-07 23:47:33

+0

這是一個非常好的解決方案。我用過這個。謝謝。 – 2013-05-28 01:52:43

+1

+1我喜歡這個比接受的答案更好。沒有必要的屬性或請求刷新,並且代碼很明顯:將文件字節讀入內存,刪除物理文件並將內存中的字節返回給用戶。謝謝! – 2014-01-22 12:25:43

17

以上的答案幫助我,這就是我結束了:

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

OnResultExecuted works,onActionExecuted不是 – RAY 2015-12-22 08:54:17

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

我在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; 
+1

沒有必要調用Content.Dispose() - 它在base.Dispose(diposing)調用中調用。 – 2016-02-17 10:15:48

+0

感謝您的輸入。 – 2016-02-28 17:34:37

0

這裏是基於@biesiad爲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 
} 
-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 
    } 
7

該解決方案可以返回其打開與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"); 

這個答案是基於Alan West的回答和Thariq Nugrohotomo的評論。

+0

這對我來說非常合適。在我看來,最簡單的解決方案。 – 2017-11-10 16:01:41