.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 分钟前
本地折扣卡 CPS 平台搭建:从系统架构到落地实战
java·开发语言·折扣卡
海上彼尚13 分钟前
Cursor 模型的强度实测排行
前端·人工智能·后端
默_笙19 分钟前
💫 给金鱼建图书馆(下):Milvus 向量数据库,让 AI 拥有长期记忆
前端·javascript
EatFan1 小时前
HTML前端利用flex解决input定位的问题
前端·css·html·css3
Java小白笔记1 小时前
Java 单元测试怎么写:JUnit 5、Mockito 与 Spring Boot 方法级实战
java·junit·单元测试
CoderYanger2 小时前
前端基础——JavaScript(WebAPI)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展
lisin-lee-cooper2 小时前
简单聊聊 Spring 框架源码
java·后端·spring
kyriewen2 小时前
AI 改祖传模块后,代码评审总绕不开两个问题
前端·程序员·ai编程
一木 之林2 小时前
七、一-AI 工程实践、插件化调试与软件交付
java·linux·c++
边境悍匪2 小时前
蜗牛学苑 Java 智能体学习 Day38|Spring AI Alibaba2 思维导图复盘
java·学习·spring