1

我收到一个创建文件并将其返回给客户端的请求。

文件发送后,我希望将其删除。

由于我收到很多请求,文件很大并且内存稀缺,我不想将它缓冲在内存中发送它。

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

Response.TransmitFile(filepath)

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

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

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

我不确定它是否有帮助,但我的控制器是从 AbpApiController 继承的。

4

3 回答 3

3

您在临时文件夹中创建文件,只需创建一个作业以根据日期/时间删除所有文件。也许给用户 4 个小时来下载文件。

于 2019-08-26T19:57:56.043 回答
0

您可以做的是从您的文件中创建一个字节数组,然后删除该文件。因此,一旦创建它,​​就将其存储在内存中,然后删除文件并返回字节数组。检查此答案以查看示例。

我希望这有帮助。

于 2019-08-26T22:51:39.790 回答
0

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);
    }
于 2019-08-27T14:24:52.933 回答