Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I would like to delete a temporary file after returning it form action. How can i achieve that with 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 !!
}

The file is too big for returning using memory stream.

like image 313
Mariusz Jamro Avatar asked Feb 27 '19 08:02

Mariusz Jamro


1 Answers

File() or PhysicalFile() return a FileResult-derived class that just delegates processing to an executor service. PhysicalFileResult's ExecuteResultAsync method calls :

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

All other FileResult-based classes work in a similar way.

The PhysicalFileResultExecutor class essentially writes the file's contents to the Response stream.

A quick and dirty solution would be to create your own PhysicalFileResult-based class that delegates to PhysicalFileResultExecutor but deletes the file once the executor finishes :

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)
    {
        try {
            await base.ExecuteResultAsync(context);
        }
        finally {
            File.Delete(FileName);
        }
    }
}

Instead of calling PhysicalFile() to create the PhysicalFileResult you can create and return a TempPhysicalFileResult, eg :

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

That's the same thing PhysicalFile() does :

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

A more sophisticated solution would be to create a custom executor that took care eg of compression as well as cleaning up files, leaving the action code clean of result formatting code

like image 155
Panagiotis Kanavos Avatar answered Sep 17 '22 13:09

Panagiotis Kanavos