ASP.NET Core 3.0中返回文件会导致内存泄漏

5
我有这个方法。
[HttpGet("view/{fileId}/{width}/{height}/{name}")]
public async Task<FileStreamResult> View(Guid fileId, int width, int height, string name)
{
    var fileInfo = await _fileViewer.GetImageInfo(fileId, width, height);
    FileStream f = new FileStream(fileInfo.FilePath, FileMode.Open);
    return File(f, fileInfo.MimeType);
}

这段代码简单地将重新调整大小的图片返回给浏览器。它可以正常工作,但据我所知,它会导致内存泄漏。

FileStream f从未被释放。

我发现我的服务器内存正在缓慢地被使用。

如果我在这里添加一个using语句,我会得到一个错误,指出流已关闭,即在文件返回给用户之前,using语句已经关闭。

应该如何正确处理呢?

更新1. 这段代码:

using (FileStream f = new FileStream(fileInfo.FilePath, FileMode.Open))
{
    return File(f, fileInfo.MimeType);
}

yields

System.ObjectDisposedException:无法访问已释放的对象。 对象名称:“无法访问已关闭的文件。”。


2
你能否包含你已经实现的 using 语句的代码?显然,正确的答案是要么显式调用 Dispose(),要么将你的 FileStream 包装在一个 using 语句中,但我们需要评估为什么你的 using 语句没有起作用。 - Jeremy Caney
1
你可以尝试将流复制到字节数组中,并使用File方法的另一个重载。在这种情况下,你可以在请求结束前关闭流。 - Yehor Androsov
如果你的假设是正确的,那么每个在他们的应用程序中使用这种结构的人都会有内存泄漏。既然他们没有,我认为你会发现不是这种方法在泄漏内存。 - Ian Kemp
3
这里是清理您传递给File方法的Stream的地方。 - Kirk Larkin
@Jens 我遇到了完全相同的问题。FileStream占用了大量内存,导致机器上的其他进程失败。你是如何解决这个问题的? - pantonis
显示剩余2条评论
1个回答

1
我建议您使用Asp.net Core文件提供程序,而不是手动使用system.IO读取文件。 https://learn.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-3.1 但是,如果您不想使用依赖注入并将fileProvider注入到控制器中,这个技巧应该适用于您:
var fileInfo = await _fileViewer.GetImageInfo(fileId, width, height);
var fileName = Path.GetFileName(fileInfo.FilePath);
IFileProvider x = new PhysicalFileProvider(Path.GetDirectoryName(fileInfo.FilePath));
IFileInfo fi =  x.GetFileInfo(fileName);
 // you can use your mime type as second argumant. (fileInfo.MimeType)
return File(fi.CreateReadStream(), MediaTypeNames.Application.Octet , fileName);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接