首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FileStreamResult -进程无法访问该文件,因为它正被另一个进程使用。

FileStreamResult -进程无法访问该文件,因为它正被另一个进程使用。
EN

Stack Overflow用户
提问于 2022-04-26 09:13:54
回答 1查看 892关注 0票数 2

ASP .NET核

MVC控制器-使用FileStream并返回FileStreamResult从服务器存储中下载文件

代码语言:javascript
复制
public IActionResult Download(string path, string fileName)
{
    var fileStream = System.IO.File.OpenRead(path);

    return File(fileStream, "application/force-download", fileName);
}

一切正常,但是一旦用户在下载完成之前取消了下载,则控制器中处理此文件的其他操作(删除文件、重命名文件)不能工作,因为:进程不能访问该文件,因为它正在被另一个进程使用。

当文件下载完成时,FileStream会自动释放,但由于某些原因,它不会在用户手动终止下载时终止。

我必须重新启动web应用程序=>,使用该文件的程序是IISExpress。

如果用户手动结束下载,请有人知道如何释放流吗?

编辑:

代码语言:javascript
复制
FileStream stream = null;
try
{
    using (stream = System.IO.File.OpenRead(path))
    {
        return File(stream, "application/force-download", fileName);
    }
}

返回FileStreamResult,后试图结束流的代码我知道它不能工作,因为return File (stream, contentType, fileName)之后它会立即跳转到块,最后流关闭,所以下载不会启动,因为流关闭了

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-26 13:50:32

看来,来源FileStreamResult类显示它不支持取消。如果需要的话,您将需要实现自己的。例如(未经测试,只是想象)

代码语言:javascript
复制
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);
                }
            }
        }
    }
}

然后你可以像这样使用它

代码语言:javascript
复制
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核心有一个完全不同的底层框架:在.net核心中,动作由和执行器处理,如来源所示。这最终会叫FileResultHelper。在这里您可以看到StreamCopyOperation是与cancellationToken context.RequestAborted一起调用的。即,取消在.net核心中的位置。

最大的问题是:为什么在您的情况下请求不被中止。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72011337

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档