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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…