根据 API 请求返回文件后删除文件

Delete file after returning it on an API request

我收到一个创建文件的请求,然后 return 将其发送给客户端。

文件发送后我想删除它。

由于请求多,文件大,内存不足,不想缓存在内存中发送。

我在不将整个文件缓冲到内存中的情况下工作的唯一方法是:

Response.TransmitFile(filepath)

问题在于它是异步执行的,所以如果我在调用之后删除它,文件下载就会中断。

我尝试调用 Flush,在 finally 块上添加删除,但这些都不起作用。想过继承HttpResponse尝试修改TransmitFile,但是是密封的class。我尝试使用 HttpResponse.ClientDisconnectedToken,但要么我不明白如何正确使用它,要么它在这种情况下不起作用。

我怎样才能做到这一点?有没有比调用 HttpResponse 的 TransmitFile 更好的方法?始终考虑到这是一个 API,文件不能分成不同的请求,并且 它不会在内存中加载完整文件

我不确定它是否能以某种方式提供帮助,但我的控制器是从 AbpApiController 继承的。

您在临时文件夹中创建文件,只需创建一个作业以删除基于 date/time 的所有文件。也许给用户 4 个小时来下载文件。

您可以做的是从您的文件创建一个字节数组,然后删除该文件。 因此,一旦创建,就将其存储在内存中,然后删除文件和 return 字节数组。 检查 this answer to see an example.

希望对您有所帮助。

TransmitFileWithLimit 的实现,它可以在很多方面进行改进,但它确实有效

HttpResponse 扩展

public static class HttpResponseExtensions
{
    public static void TransmitFileWithLimit(this HttpResponse response, string path, int limit)
    {
        var buffer = new byte[limit];
        var offset = 0;
        response.ClearContent();
        response.Clear();
        response.ContentType = "text/plain";

        using (var fileStream = File.OpenRead(path))
        {
            var lengthStream = fileStream.Length;
            while (offset < lengthStream)
            {
                var lengthBytes = fileStream.Read(buffer, 0, limit);
                var chars = System.Text.Encoding.ASCII.GetString(buffer, 0, lengthBytes).ToCharArray();
                response.Write(chars, 0, lengthBytes);
                offset += lengthBytes;
            }
        }
        response.Flush();
        response.End();
    }
}

内部控制器

    public void Get()
    {
        var path = @"C:\temporal\bigfile.mp4";
        var response = HttpContext.Current.Response;
        response.ClearContent();
        response.Clear();
        response.AddHeader("Content-Disposition", "inline; filename=" + HttpUtility.UrlPathEncode(path));
        response.ContentType = "text/plain";
        response.AddHeader("Content-Length", new FileInfo(path).Length.ToString());
        response.Flush();
        HttpContext.Current.ApplicationInstance.CompleteRequest();

        TransmitFileWithLimit(path, 10000);
        File.Delete(path);
    }