首页 新闻 会员 周边

请教:.NET Core3.1为什么在nginx下同步IO会不起作用?

0
悬赏园豆:200 [待解决问题]


/// <summary>
/// 文件中转下载
/// </summary>
/// <param name="FilePath">文件相对路径</param>
/// <returns></returns>
[HttpGet]
public void DownloadFile1([FromQuery] string FilePath)
{
try
{
string filePath = GlobalConfig.Com.WebPath.UserResourcePath + FilePath; //文件物理路径
if (!System.IO.File.Exists(filePath))
{
LogHelper.Info($"客户端下载文件失败:文件不存在,文件绝对路径:{filePath}", LogHelper.GetCurSourceFileName(), LogHelper.GetLineNum());
return;
}
string fileName = Path.GetFileName(filePath);
long beginPosition = 0;
var fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, true);

            //断点续传
            string rangeStr = Request.Headers["range"];  //range 参数格式:byte=1024-,这个是http协议的格式,也可以自定义格式
            if (!string.IsNullOrEmpty(rangeStr))  //断点续传
            {
                string byteStr = rangeStr.Split("=")?[1];
                if (!string.IsNullOrEmpty(byteStr))
                {
                    var byteArr = byteStr.Split("-");
                    if (byteArr != null && byteArr.Length > 1)
                    {
                        beginPosition = Convert.ToInt64(byteArr[0]);
                    }
                }
            }

            HttpContext.Response.ContentType = "application/octet-stream";
            HttpContext.Response.Headers.Append("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName));
            HttpContext.Response.Headers.Append("Charset", "utf-8");
            HttpContext.Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition");
            int bufferSize = 1024;  //每次读取1MB到服务器内存

            using (HttpContext.Response.Body)
            {
                long contentLength = fs.Length;
                HttpContext.Response.ContentLength = contentLength;
                byte[] buffer;
                long hasRead = 0;
                while (hasRead < contentLength)
                {
                    if (HttpContext.RequestAborted.IsCancellationRequested)
                    {
                        //取消下载会进来,这里可以做一些操作。。。。。
                        break;
                    }

                    fs.Seek(hasRead, SeekOrigin.Begin);
                    buffer = new byte[bufferSize];
                    //从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中
                    int currentRead = fs.Read(buffer, 0, bufferSize);
                    HttpContext.Response.Body.WriteAsync(buffer, 0, currentRead);
                    HttpContext.Response.Body.Flush();
                    hasRead += currentRead;
                }

                if (hasRead == contentLength)  //下载完成
                {
                    //下载完成之后要做的事。。。。
                    return;
                }
            }

        }
        catch (Exception ex)
        {
            LogHelper.Error("客户端下载文件出现异常:", ex, LogHelper.GetCurSourceFileName(), LogHelper.GetLineNum());
            return;
        }
    }

文件下载:这里使用的是同步方法,在本地测试和Linux下命令行启动项目,都是没问题的,等整个文件下载完成才会往下走,但是在nginx代理下,就会出现异步情况:文件下载一部分,就走到下面了,不理解。。。。。

注释:至于为什么要用同步方法,是因为我们的需求是:下载文件之后需要扣除平台的流量(充值获得)。。。。。

汪小让的主页 汪小让 | 初学一级 | 园豆:4
提问于:2022-06-17 17:48
< >
分享
所有回答(2)
0

建议试试 Response.Body 的 CopyTo 方法

using (var fs = new FileStream(filepath, FileMode.Open))
{
    HttpContext.Response.Body.CopyTo(fs);
}
dudu | 园豆:30979 (高人七级) | 2022-06-17 18:12

另外,FileStream 没有 Dispose 是个隐患

var fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, true);
支持(0) 反对(0) dudu | 园豆:30979 (高人七级) | 2022-06-17 18:13

问题可能是 HttpContext.Response.Body.Flush(); 引起的,建议将之移动到 while 循环的外面

支持(0) 反对(0) dudu | 园豆:30979 (高人七级) | 2022-06-17 23:19

@dudu: 还是没能解决这个问题,就是我的文件还在下载的时候,就已经到了下面了

支持(0) 反对(0) 汪小让 | 园豆:4 (初学一级) | 2022-06-20 08:45

@汪小让: 建议去掉 using (HttpContext.Response.Body) 这个地方的 using

支持(0) 反对(0) dudu | 园豆:30979 (高人七级) | 2022-06-20 09:25
0

可能是某个nginx参数超限制导致请求中断了,检查一下nginx转发的内容大小限制、请求超时看看,先试着把参数调大看看。

启用Kestrel详细日志,观察请求 ConnectionId 是否有变化

Adming | 园豆:119 (初学一级) | 2022-07-18 09:53
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册