FileStreamResult - 该进程无法访问该文件,因为它正被另一个进程使用
FileStreamResult - The process cannot access the file, because it is being used by another process
ASP.NET 核心
MVC 控制器 - 使用 FileStream 从服务器存储下载文件并返回 FileStreamResult
public IActionResult Download(string path, string fileName)
{
var fileStream = System.IO.File.OpenRead(path);
return File(fileStream, "application/force-download", fileName);
}
一切正常,但是一旦用户在下载完成前取消下载,控制器中的其他操作使用此文件(删除文件,重命名file) 不起作用,因为:进程无法访问该文件,因为它正被另一个进程使用
FileStream 在文件下载完成后自动处理,但由于某些原因,当用户手动终止下载时它并没有终止。
我必须重新启动 Web 应用程序 => 使用该文件的程序是 IISExpress
如果用户手动结束下载,有人知道如何处理流吗?
编辑:
FileStream stream = null;
try
{
using (stream = System.IO.File.OpenRead(path))
{
return File(stream, "application/force-download", fileName);
}
}
我试图在返回 FileStreamResult 后结束 Stream 的代码,我知道它不能工作,因为在 return File (stream, contentType, fileName)
之后它立即跳转到块 finally 并且 stream 关闭,因此下载没有开始,因为 stream 已关闭
FileStreamResult
class的source好像不支持取消。
如果需要,您需要自己实施。例如。 (not-tested,纯属想象)
using System.IO;
namespace System.Web.Mvc
{
public class CancellableFileStreamResult : FileResult
{
// default buffer size as defined in BufferedStream type
private const int BufferSize = 0x1000;
private readonly CancellationToken _cancellationToken;
public CancellableFileStreamResult(Stream fileStream, string contentType,
CancellationToken cancellationToken)
: base(contentType)
{
if (fileStream == null)
{
throw new ArgumentNullException("fileStream");
}
FileStream = fileStream;
_cancellationToken = cancellationToken;
}
public Stream FileStream { get; private set; }
protected override void WriteFile(HttpResponseBase response)
{
// grab chunks of data and write to the output stream
Stream outputStream = response.OutputStream;
using (FileStream)
{
byte[] buffer = new byte[BufferSize];
while (!_cancellationToken.IsCancellationRequested)
{
int bytesRead = FileStream.Read(buffer, 0, BufferSize);
if (bytesRead == 0)
{
// no more data
break;
}
outputStream.Write(buffer, 0, bytesRead);
}
}
}
}
}
你可以像这样使用它
public IActionResult Download(string path, string fileName, CancellationToken cancellationToken)
{
var fileStream = System.IO.File.OpenRead(path);
var result = new CancellableFileStreamResult(
fileStream, "application/force-download", cancellationToken);
result.FileDownloadName = fileName;
return result;
}
再说一次,我这不是测试,只是想象。
可能这不行,因为动作已经结束,不能再取消了。
编辑:
上述回答“想象”为 ASP.net 框架。 ASP.net core有一个完全不同的底层框架:在.net core中,action由and executor处理,如the source. That will eventually call WriteFileAsync
in the FileResultHelper
所示。在那里您可以看到 StreamCopyOperation
是使用 cancellationToken context.RequestAborted
调用的。 IE。 .net Core 中取消了。
最大的问题是:为什么在您的情况下请求没有中止。
ASP.NET 核心
MVC 控制器 - 使用 FileStream 从服务器存储下载文件并返回 FileStreamResult
public IActionResult Download(string path, string fileName)
{
var fileStream = System.IO.File.OpenRead(path);
return File(fileStream, "application/force-download", fileName);
}
一切正常,但是一旦用户在下载完成前取消下载,控制器中的其他操作使用此文件(删除文件,重命名file) 不起作用,因为:进程无法访问该文件,因为它正被另一个进程使用
FileStream 在文件下载完成后自动处理,但由于某些原因,当用户手动终止下载时它并没有终止。
我必须重新启动 Web 应用程序 => 使用该文件的程序是 IISExpress
如果用户手动结束下载,有人知道如何处理流吗?
编辑:
FileStream stream = null;
try
{
using (stream = System.IO.File.OpenRead(path))
{
return File(stream, "application/force-download", fileName);
}
}
我试图在返回 FileStreamResult 后结束 Stream 的代码,我知道它不能工作,因为在 return File (stream, contentType, fileName)
之后它立即跳转到块 finally 并且 stream 关闭,因此下载没有开始,因为 stream 已关闭
FileStreamResult
class的source好像不支持取消。
如果需要,您需要自己实施。例如。 (not-tested,纯属想象)
using System.IO;
namespace System.Web.Mvc
{
public class CancellableFileStreamResult : FileResult
{
// default buffer size as defined in BufferedStream type
private const int BufferSize = 0x1000;
private readonly CancellationToken _cancellationToken;
public CancellableFileStreamResult(Stream fileStream, string contentType,
CancellationToken cancellationToken)
: base(contentType)
{
if (fileStream == null)
{
throw new ArgumentNullException("fileStream");
}
FileStream = fileStream;
_cancellationToken = cancellationToken;
}
public Stream FileStream { get; private set; }
protected override void WriteFile(HttpResponseBase response)
{
// grab chunks of data and write to the output stream
Stream outputStream = response.OutputStream;
using (FileStream)
{
byte[] buffer = new byte[BufferSize];
while (!_cancellationToken.IsCancellationRequested)
{
int bytesRead = FileStream.Read(buffer, 0, BufferSize);
if (bytesRead == 0)
{
// no more data
break;
}
outputStream.Write(buffer, 0, bytesRead);
}
}
}
}
}
你可以像这样使用它
public IActionResult Download(string path, string fileName, CancellationToken cancellationToken)
{
var fileStream = System.IO.File.OpenRead(path);
var result = new CancellableFileStreamResult(
fileStream, "application/force-download", cancellationToken);
result.FileDownloadName = fileName;
return result;
}
再说一次,我这不是测试,只是想象。 可能这不行,因为动作已经结束,不能再取消了。
编辑:
上述回答“想象”为 ASP.net 框架。 ASP.net core有一个完全不同的底层框架:在.net core中,action由and executor处理,如the source. That will eventually call WriteFileAsync
in the FileResultHelper
所示。在那里您可以看到 StreamCopyOperation
是使用 cancellationToken context.RequestAborted
调用的。 IE。 .net Core 中取消了。
最大的问题是:为什么在您的情况下请求没有中止。