ASP.NET Core实现课程文件打包为ZIP格式提供下载的解决方案
课程资源打包ZIP下载实现方案
实现思路
直接使用.NET内置的System.IO.Compression.ZipArchive类完成打包,无需引入第三方依赖,可同时支持单文件打包、多文件批量打包两种场景。核心逻辑是将待下载的课程文件写入内存ZIP包,再返回ZIP的字节流供用户下载。
改造后的代码实现
单文件打包版本(适配现有单课时下载逻辑)
using System.IO.Compression; public Tuple<byte[],string,string> DownloadFile(long episodeId) { var episode = _context.CourseEpisodes.Find(episodeId); string filepath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/courseFiles", episode.FileName); // 权限校验逻辑保持不变 if(episode.IsFree || (_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated && IsuserIncorse(_httpContextAccessor.HttpContext.User.Identity.Name, episode.CourseId))) { // 内存中生成ZIP包 using (var memoryStream = new MemoryStream()) { using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) { // 向ZIP包中添加课程文件 var zipEntry = archive.CreateEntry(episode.FileName, CompressionLevel.Optimal); using (var entryStream = zipEntry.Open()) using (var fileStream = System.IO.File.OpenRead(filepath)) { fileStream.CopyTo(entryStream); } } memoryStream.Position = 0; byte[] zipFileBytes = memoryStream.ToArray(); // 返回ZIP包,修改文件名和响应类型 string zipFileName = Path.GetFileNameWithoutExtension(episode.FileName) + ".zip"; return Tuple.Create(zipFileBytes, "application/zip", zipFileName); } } return null; }
多文件批量打包扩展(适配整课程下载需求)
如果需要支持用户下载整个课程的所有课时资源,新增方法即可:
// courseId为要下载的课程ID public Tuple<byte[],string,string> DownloadWholeCourse(long courseId) { // 先做用户权限校验,确认用户有权限下载该课程 if(!_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated || !IsuserIncorse(_httpContextAccessor.HttpContext.User.Identity.Name, courseId)) { return null; } // 查询该课程下所有课时的文件 var allEpisodes = _context.CourseEpisodes.Where(e => e.CourseId == courseId).ToList(); string courseFileRoot = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/courseFiles"); using (var memoryStream = new MemoryStream()) { using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) { foreach (var episode in allEpisodes) { var filePath = Path.Combine(courseFileRoot, episode.FileName); if (!System.IO.File.Exists(filePath)) continue; // 跳过不存在的文件 var zipEntry = archive.CreateEntry(episode.FileName, CompressionLevel.Optimal); using (var entryStream = zipEntry.Open()) using (var fileStream = System.IO.File.OpenRead(filePath)) { fileStream.CopyTo(entryStream); } } } memoryStream.Position = 0; byte[] zipFileBytes = memoryStream.ToArray(); string zipFileName = $"课程_{courseId}_全部资源.zip"; return Tuple.Create(zipFileBytes, "application/zip", zipFileName); } }
优化建议
- 若课程文件总大小超过1G,不要使用内存打包方式,改为先在本地磁盘生成临时ZIP文件,读取返回后异步删除临时文件,避免服务端内存溢出
- 可根据需求调整
CompressionLevel压缩级别,平衡压缩速度和包大小 - 文件名如果包含中文,需要做编码适配,避免不同浏览器下载时文件名乱码
内容的提问来源于stack exchange,提问作者zari
相关产品推荐
相关产品推荐

