簡體   English   中英

如何在ASP.NET Core中流式傳輸后刪除文件

[英]How to delete a file after it was streamed in ASP.NET Core

我想在返回表單操作后刪除一個臨時文件。 我如何使用ASP.NET Core實現這一目標:

public IActionResult Download(long id)
{
    var file = "C:/temp/tempfile.zip";
    var fileName = "file.zip;
    return this.PhysicalFile(file, "application/zip", fileName);
    // I Would like to have File.Delete(file) here !!
}

該文件太大,無法使用內存流返回。

File()PhysicalFile()返回一個FileResult派生類, FileResult 將處理委托給執行程序服務。 PhysicalFileResultExecuteResultAsync方法調用:

var executor = context.HttpContext.RequestServices
                 .GetRequiredService<IActionResultExecutor<PhysicalFileResult>>();
return executor.ExecuteAsync(context, this);

所有其他基於FileResult的類以類似的方式工作。

PhysicalFileResultExecutor類實質上將文件的內容寫入Response流。

一個快速而骯臟的解決方案是創建自己的基於PhysicalFileResult的類,該類委托給PhysicalFileResultExecutor但是在執行程序完成后刪除文件:

public class TempPhysicalFileResult : PhysicalFileResult
{
    public TempPhysicalFileResult(string fileName, string contentType)
                 : base(fileName, contentType) { }
    public TempPhysicalFileResult(string fileName, MediaTypeHeaderValue contentType)
                 : base(fileName, contentType) { }

    public override async  Task ExecuteResultAsync(ActionContext context)
    {
        await base.ExecuteResultAsync(context);
        File.Delete(FileName);
    }
}

您可以創建並返回TempPhysicalFileResult ,而不是調用PhysicalFile()來創建PhysicalFileResult ,例如:

return new TempPhysicalFileResult(file, "application/zip"){FileDownloadName=fileName};

這與PhysicalFile()的作用相同:

[NonAction]
public virtual PhysicalFileResult PhysicalFile(
    string physicalPath,
    string contentType,
    string fileDownloadName)
    => new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName };

一個更復雜的解決方案是創建一個自定義執行程序,負責處理壓縮和清理文件,使動作代碼保持清除結果格式代碼

在流式傳輸完成后,請求在同一請求中很難做到這一點。 更好的選擇可能是通過托管服務運行定時后台任務,該服務定期從臨時目錄中刪除所有文件(例如,上次寫入時間> 5分鍾)。

您可以加載文件的內容。 刪除文件並發送內容作為響應。 在MVC中,您可以返回一個文件作為響應。 檢查下面的代碼段

public FileResult Download()
{
    var fileName = $"client-file-name.ext";
    var filepath = $"filepath";
    byte[] fileBytes = System.IO.File.ReadAllBytes(filepath);
    //delete file here
    return File(fileBytes, "application/x-msdownload", fileName);
}

由於文件很大,所以解決方案是在請求旁邊發送令牌(如guid)。 只有在下載完成后才能刪除該文件(否則您可能會丟失該文件)。 因此,使用該令牌,客戶端將使用上述令牌發出新請求。 因此,您將知道下載成功,並且您可以繼續刪除該文件。

我建議使用Dictionary將令牌映射到文件。

由於您很容易丟失文件,因此刪除一個請求似乎是一種不好的做法。

此外,您可以使用Henk Mollema答案確保所有文件都定期清除,如果這是您要實現的目標。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM