.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;
        }
    }
相关推荐
嘤国大力士28 分钟前
C++11&QT复习 (十六)
java·开发语言·c++
菜鸟起航ing28 分钟前
【Java面试系列】Spring Boot中自动配置原理与自定义Starter开发实践详解 - 3-5年Java开发必备知识
java·spring boot·面试·自动配置·自定义starter
李白的粉31 分钟前
基于springboot+vue的课程管理系统
java·毕业设计·课程设计·源代码·课程管理系统
DDDiccc32 分钟前
SpringCloud微服务(一)Eureka+Nacos
java·spring cloud·微服务
前端.火鸡36 分钟前
认识vue中的install和使用场景
前端·javascript·vue.js
橘猫云计算机设计38 分钟前
ASP.NET图书馆借阅系统(源码+lw+部署文档+讲解),源码可白嫖!
java·数据库·后端·爬虫·小程序·毕业设计·asp.net
念九_ysl43 分钟前
Java中的列表(List):操作与实现详解
java·开发语言·list
摆烂工程师44 分钟前
Grok3 支持 DeeperSearch 的免费可用次数的查询了
前端·后端·程序员
pubuzhixing44 分钟前
在线白板 - 如何从零实现一个自由画笔
前端·开源
追逐时光者1 小时前
一款基于 .NET 8 + Vue 开源的、企业级中后台权限管理系统
后端·.net