Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
647 views
in Technique[技术] by (71.8m points)

c# - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...