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

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

cs 复制代码
	/// <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下载(取消下载服务端知道)

cs 复制代码
	/// <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;
        }
    }
相关推荐
皎味小行家12 分钟前
第四十六天|动态规划|子序列|647. 回文子串,5.最长回文子串, 516.最长回文子序列,动态规划总结篇
java·数据结构·算法·leetcode·动态规划
LUCIAZZZ16 分钟前
通过代理模式理解Java注解的实现原理
java·开发语言·数据库·spring boot·mysql·spring·代理模式
计算机-秋大田24 分钟前
基于Spring Boot的图书个性化推荐系统的设计与实现(LW+源码+讲解)
java·前端·spring boot·后端·spring·课程设计
m0_7482365827 分钟前
【Spring Boot】统一异常处理
java·spring boot·后端
肘击鸣的百k路28 分钟前
处理Spring MVC 中的跨域问题
java·spring·mvc
我不当帕鲁谁当帕鲁28 分钟前
arcgis for js范围内天地图高亮,其余底图灰暗
前端·javascript·arcgis
步、步、为营34 分钟前
C# foreach循环:性能提升
windows·c#·.net
sniper_fandc39 分钟前
详解享元模式
java·设计模式·享元模式
一个人的幽默1 小时前
java将list转成树结构
java·list
二掌柜,酒来!1 小时前
Java中未检查类型转换的隐患:从List<Map>到List<Student>的映射问题解析
java·list