Bootstrap

.NET 8 WebAPI文件下载包含断点续传和取消下载

一、文件下载(取消下载服务端不会知道)

	/// <summary>
    /// 文件下载
    /// </summary>
    /// <param name="FilePath">文件相对路径</param>
    /// <returns></returns>
    [HttpGet]
    public IActionResult DownloadFile([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 new EmptyResult();
            }

            string fileName = Path.GetFileName(filePath);
            var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, 4096, true);  //异步读取文件

            return File(fileStream, "application/octet-stream", fileName, true);  //为true时,支持断点续传
        }
        catch (Exception ex)
        {
            LogHelper.Error("客户端下载文件出现异常:", ex, LogHelper.GetCurSourceFileName(), LogHelper.GetLineNum());
            return new EmptyResult();
        }
    }

二、.NET Core 写Response.Body下载(取消下载服务端知道)

	/// <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;
        }
    }

;