2010-01-11 24 views
22

Tôi muốn xóa tệp ngay sau khi tải xuống, làm cách nào để thực hiện? Tôi đã cố gắng để phân lớp FilePathResult và ghi đè lên WriteFile phương pháp mà tôi xóa tập tin sau khiLàm thế nào để xóa tập tin sau khi tải về với ASP.NET MVC?

HttpResponseBase.TransmitFile 

được gọi, nhưng điều này bị treo ứng dụng.

Tôi có thể xóa tệp an toàn sau khi người dùng tải xuống không?

+0

Giải pháp phải đi trong 'câu trả lời', không phải trong câu hỏi. –

Trả lời

11

Bạn có thể tạo một actionfilter tùy chỉnh cho các hành động với một phương pháp OnActionExecuted mà sau đó sẽ loại bỏ các tập tin sau khi hành động được hoàn thành, một cái gì đó giống như

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

sau đó hành động của bạn có

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

Tải xuống bị treo và không bao giờ kết thúc, ý tưởng? – Valentin

+0

Tất nhiên, tôi không nghĩ, bạn đang xóa tệp trước khi quá trình tải xuống hoàn tất. Bạn có thể không xóa các tập tin được tạo trước đó trước mỗi yêu cầu cho một kết quả mới, đó là những gì tôi đã làm trong một tình huống tương tự như âm thanh. – Israfel

+0

hiện điều này cho phép giải pháp – Krunal

1

My mẫu đã sử dụng.

1) Tạo tệp.

2) Xóa tập tin được tạo cũ, FileInfo.CreationTime < DateTime.Now.AddHour (-1)

3) tài khoản được tải về.

Ý tưởng này như thế nào?

+0

Xin vui lòng xem câu trả lời của tôi, nó thực sự hoạt động ngay bây giờ – Valentin

1

SOLUTION:

Một trong hai nên phân lớp các FileResult hoặc tạo một bộ lọc hành động tùy chỉnh, nhưng phần khó khăn là để tuôn ra những câu trả lời trước khi cố gắng để xóa các tập tin.

27

Tạo tệp và lưu tệp.
Response.Flush() gửi tất cả dữ liệu cho khách hàng.
Sau đó, bạn có thể xóa tệp tạm thời.

này làm việc cho tôi:

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

Làm việc một điều trị, cảm ơn rất nhiều! – wheelibin

+0

Nó cũng sẽ hoạt động với các tệp lớn (lớn hơn 512 Mb)? – vibs2006

4

trọng phương pháp OnResultExecuted có lẽ là giải pháp đúng .. Phương pháp này chạy sau khi phản ứng được viết.

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

đang hành động:

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

đọc trong các byte của tập tin, xóa nó, gọi hành động tập tin bộ điều khiển cơ sở của.

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, bạn có thể tránh phương pháp này nếu bạn đang xử lý các tệp rất lớn và bạn lo lắng về mức tiêu thụ bộ nhớ.

+0

bạn có chắc đây là câu trả lời hợp lệ cho câu hỏi này không? – Oerd

+0

Đây là một giải pháp rất tốt. Tôi đã sử dụng cái này. Cảm ơn. –

+1

+1 Tôi thích cái này tốt hơn câu trả lời được chấp nhận. Không có thuộc tính hoặc yêu cầu flushing yêu cầu, và mã là rõ ràng: Đọc các filebytes vào bộ nhớ, xóa các tập tin phisical và trả lại các byte từ bộ nhớ cho người dùng. Cảm ơn! –

17

câu trả lời trên đã giúp tôi, đây là những gì tôi đã kết thúc với:

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

Các tác phẩm OnResultExecuted, onActionExecuted không – RAY

2

Hãy thử này. Điều này sẽ hoạt động đúng.

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

Tôi đã thực hiện cùng một hành động trong WebAPI. Tôi cần xóa tệp ngay sau khi tải xuống máy chủ biểu mẫu. Chúng tôi có thể tạo lớp thông báo phản hồi tùy chỉnh. Nó lấy đường dẫn tệp làm tham số và xóa nó sau khi nó được truyền đi.

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

Sử dụng lớp này dưới dạng mã và sẽ xóa tệp của bạn khi tệp được ghi trên luồng phản hồi.

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

Nó không cần thiết để gọi 'Content.Dispose()' - nó được gọi trong lệnh 'base.Dispose (diposing)'. –

+0

Cảm ơn bạn đã nhập. –

0

đây được cập nhật câu trả lời dựa trên giải pháp thanh lịch bởi @biesiad cho ASP.NET MVC (https://stackoverflow.com/a/4488411/1726296)

Về cơ bản nó sẽ trả về EmptyResult sau phản ứng được gửi đi.

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

Tôi đã gửi giải pháp này trong 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

Bạn có thể trở lại chỉ thường xuyên FileStreamResult được mở với FileOptions.DeleteOnClose. Luồng tệp sẽ được xử lý với kết quả của asp.net. Câu trả lời này không yêu cầu sử dụng các phương thức đáp ứng mức thấp có thể gây phản tác dụng trong một số tình huống nhất định. Ngoài ra không có thêm công việc sẽ được thực hiện như tải tập tin vào bộ nhớ như toàn bộ.

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

Câu trả lời này dựa trên câu trả lời của Alan West và bình luận của Thariq Nugrohotomo.

+0

Điều này làm việc hoàn hảo cho tôi. Giải pháp đơn giản nhất, theo ý kiến ​​của tôi. –

Các vấn đề liên quan