导读:本期聚焦于小伙伴创作的《C#如何实现WebAPI文件断点下载?Range请求文件分段下载教程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何实现WebAPI文件断点下载?Range请求文件分段下载教程》有用,将其分享出去将是对创作者最好的鼓励。

在C#开发的WebAPI项目中实现文件断点下载,核心是通过处理HTTP协议中的Range请求头,让服务端能够返回文件指定区间的内容,避免客户端重复下载已获取的文件片段。这种方式特别适合大文件下载场景,能有效提升下载成功率,减少带宽浪费。

C#如何实现WebAPI文件断点下载?Range请求文件分段下载教程

断点下载的核心原理

HTTP协议中的Range请求头用于指定客户端需要获取的资源范围,格式通常为Range: bytes=start-end,其中start是起始字节位置,end是结束字节位置,如果省略end则表示从start到文件末尾。服务端收到Range请求后,需要返回状态码为206 Partial Content的响应,同时在响应头中设置Content-Range字段说明返回的内容范围,以及Accept-Ranges: bytes告知客户端支持字节范围请求。

WebAPI中实现断点下载的步骤

1. 解析Range请求头

首先从当前请求的头部获取Range信息,解析出客户端需要的起始和结束字节位置。如果请求中没有Range头,则按照普通下载处理,返回完整文件。

2. 读取文件指定区间内容

根据解析出的字节范围,使用文件流读取对应区间的文件内容,避免一次性加载整个文件到内存,减少内存占用。

3. 设置正确的响应头

根据是否处理Range请求,设置对应的响应状态码和响应头,确保客户端能正确识别返回的内容范围。

完整代码实现

以下是一个完整的C# WebAPI控制器示例,实现了文件断点下载功能:

using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web.Http;

namespace FileDownloadDemo.Controllers
{
    public class FileDownloadController : ApiController
    {
        // 文件存储目录,实际项目中可根据需求调整
        private static readonly string FileStoragePath = AppDomain.CurrentDomain.BaseDirectory + "UploadFiles\";

        /// <summary>
        /// 文件断点下载接口
        /// </summary>
        /// <param name="fileName">要下载的文件名</param>
        /// <returns>文件内容响应</returns>
        [HttpGet]
        public HttpResponseMessage DownloadFile(string fileName)
        {
            // 拼接文件完整路径
            string filePath = Path.Combine(FileStoragePath, fileName);
            // 检查文件是否存在
            if (!File.Exists(filePath))
            {
                return new HttpResponseMessage(HttpStatusCode.NotFound)
                {
                    Content = new StringContent("请求的文件不存在")
                };
            }

            // 获取文件信息
            FileInfo fileInfo = new FileInfo(filePath);
            long fileLength = fileInfo.Length;
            // 初始化起始和结束位置
            long startBytes = 0;
            long endBytes = fileLength - 1;
            bool isRangeRequest = false;

            // 获取当前请求的Range头
            HttpRequestMessage request = Request;
            if (request.Headers.Range != null && request.Headers.Range.Ranges.Count > 0)
            {
                isRangeRequest = true;
                RangeItemHeaderValue range = request.Headers.Range.Ranges[0];
                // 解析起始位置,如果未指定则默认为0
                if (range.From.HasValue)
                {
                    startBytes = range.From.Value;
                }
                // 解析结束位置,如果未指定则默认为文件末尾
                if (range.To.HasValue)
                {
                    endBytes = range.To.Value;
                }
                // 校验范围合法性,避免越界
                if (startBytes > endBytes || startBytes >= fileLength)
                {
                    return new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable)
                    {
                        Content = new StringContent("请求的Range范围不合法")
                    };
                }
                if (endBytes >= fileLength)
                {
                    endBytes = fileLength - 1;
                }
            }

            // 创建响应对象
            HttpResponseMessage response = new HttpResponseMessage();
            // 设置响应头,告知客户端支持字节范围请求
            response.Headers.AcceptRanges.Add("bytes");
            // 设置Content-Type为application/octet-stream,通用二进制流类型
            response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            // 设置文件名,避免中文乱码
            string encodedFileName = Uri.EscapeDataString(fileName);
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileNameStar = encodedFileName
            };

            if (isRangeRequest)
            {
                // 处理Range请求,返回206状态码
                response.StatusCode = HttpStatusCode.PartialContent;
                // 设置Content-Range头,格式为 bytes start-end/totalLength
                response.Content.Headers.ContentRange = new ContentRangeHeaderValue(startBytes, endBytes, fileLength);
                // 设置返回的内容长度为当前区间的字节数
                response.Content.Headers.ContentLength = endBytes - startBytes + 1;
                // 调整文件流的起始位置
                response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read));
                // 跳过已读取的字节
                response.Content.ReadAsStreamAsync().Result.Seek(startBytes, SeekOrigin.Begin);
            }
            else
            {
                // 普通下载,返回完整文件,状态码200
                response.StatusCode = HttpStatusCode.OK;
                response.Content.Headers.ContentLength = fileLength;
            }

            return response;
        }
    }
}

注意事项

  • 文件路径需要做好安全校验,避免客户端通过构造文件名访问非授权目录的文件,比如可以校验文件名只允许包含字母、数字、下划线和点,禁止包含路径分隔符。
  • 大文件下载时建议使用异步方法处理,避免阻塞线程,提升接口并发能力。
  • 如果文件需要权限校验,需要在下载接口中添加身份验证逻辑,确保只有有权限的用户才能下载对应文件。
  • 测试时可以使用支持断点续传的下载工具,比如迅雷、Postman等,发送Range请求验证功能是否正常。

C#WebAPIRange请求断点下载文件分段下载修改时间:2026-06-28 06:39:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。