在ASP.NET Core中传输文件后如何删除文件

时间:2019-02-27 08:55:56

标签: c# asp.net-core asp.net-core-mvc

我想在返回临时文件后删除它。我如何使用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 !!
}

文件太大,无法使用内存流返回。

4 个答案:

答案 0 :(得分:2)

File()PhysicalFile()delegates processing派生到FileResult的类返回给执行者服务。 PhysicalFileResult的{​​{3}}方法调用:

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

所有其他基于FileResult的类都以类似的方式工作。

ExecuteResultAsync类实际上是将文件的内容写入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);
    }
}

您可以创建并返回一个PhysicalFile(),而不是调用PhysicalFileResult来创建TempPhysicalFileResult,例如:

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

PhysicalFileResultExecutor的操作与此相同:

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

更复杂的解决方案是创建一个自定义执行器,该执行器负责压缩和清理文件,而动作代码不包含结果格式代码

答案 1 :(得分:0)

在流完成后直接结束请求的同一请求中,很难做到这一点。更好的选择可能是运行定时后台任务via a hosted service,该任务会定期从temp目录中删除所有文件(例如,上次写入时间大于5分钟的文件)。

答案 2 :(得分:0)

您可以加载文件的内容。删除文件并发送内容作为响应。在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);
}

答案 3 :(得分:0)

由于文件很大,一种解决方案是在请求旁边发送令牌(如guid)。仅在下载完成后,您才想删除该文件(否则可能会丢失该文件)。因此,使用该令牌,客户端将使用上述令牌发出新请求。因此,您将知道下载成功,并且可以继续删除文件了。

我建议使用字典将令牌映射到文件。

由于您很容易丢失文件,因此删除一个请求似乎是一种不好的做法。

此外,您可以使用Henk Mollema答案来确定是否要定期清除所有文件。