最近由于工作和个人事务,站点也好久没更新了,但这并不影响我对.NET的热情。站点的更新工作还是得想办法抽时间来完成的。
今天利用中午的时间来写一篇关于Asp.Net Web Api下载文件的文章,之前我也写过类似的文章,请见:《ASP.NET(C#) Web Api通过文件流下载文件的实例》
本文以这篇文章的基础,提供了ByteArrayContent的下载以及在下载多个文件时实现在服务器对多文件进行压缩打包后下载的功能。
关于本文中实现的在服务器端用.NET压缩打包文件功能的过程中,使用到了一个第方类库:DotNetZip,具体的使用将在正文中涉及。好了,描述了这么多前言,下面我们进入本文示例的正文。
1.首先创建名为:WebApiDownload的Web Api 项目(C#);
2.接着新建一个空的控制器,命名为:DownloadController;
3.创建一些打包文件和存放临时文件的文件夹(downloads),具体请看本文最后提供的示例项目代码
4.打开NuGet程序包管事器,搜索DotNetZip,如下图:
搜索到DotNetZip安装包后,进行安装,以便用于本项目将要实现多文件打包压缩的功能,如下图:
安装完成DotNetZip包后,我们就可以退出NuGet程序包管理器了,因为本项目为示例项目,不需再添加其他的包。
5.在Models文件夹下创建一个示例数据的类,名为:DemoData,其中的成员和实现如下:
using System.Collections.Generic; namespace WebApiDownload.Models { public class DemoData { public static readonly List<List<string Contacts = new List<List<string(); public static readonly List<string> File1 = new List<string> { "f_1_test_1@example.com", "f_1_test_2@example.com", "f_1_test_3@example.com", "f_1_test_4@example.com", "f_1_test_5@example.com" }; public static readonly List<string> File2 = new List<string> { "f_2_test_1@example.com", "f_2_test_2@example.com", "f_2_test_3@example.com", "f_2_test_4@example.com", "f_2_test_5@example.com" }; public static readonly List<string> File3 = new List<string> { "f_3_test_1@example.com", "f_3_test_2@example.com", "f_3_test_3@example.com", "f_3_test_4@example.com", "f_3_test_5@example.com" }; public static List<List<string GetMultiple { get { if (Contacts.Count <= 0) { Contacts.Add(File1); Contacts.Add(File2); Contacts.Add(File3); } return Contacts; } } } }
6.到这里,我们的准备工作基本做得差不多了,最后我们只需要在DownloadController控制器中实现两个Action,一个为:DownloadSingle(提供下载单个文件的功能),另一个为:DownloadZip(提供打包压缩多个文件并下载的功能)。具体的DownloadController完整代码如下:
using System.Linq; using System.Net.Http; using System.Text; using System.Web.Http; using Ionic.Zip; using WebApiDownload.Models; using System; using System.IO; using System.Net; using System.Net.Http.Headers; using System.Threading; using System.Web; namespace WebApiDownload.Controllers { [RoutePrefix("download")] public class DownloadController : ApiController { [HttpGet, Route("single")] public HttpResponseMessage DownloadSingle() { var response = new HttpResponseMessage(); //从List集合中获取byte[] var bytes = DemoData.File1.Select(x => x + "\n").SelectMany(x => Encoding.UTF8.GetBytes(x)).ToArray(); try { var fileName = string.Format("download_single_{0}.txt", DateTime.Now.ToString("yyyyMMddHHmmss")); var content = new ByteArrayContent(bytes); response.Content = content; response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = fileName }; response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); } catch (Exception ex) { response.StatusCode = HttpStatusCode.InternalServerError; response.Content = new StringContent(ex.ToString()); } return response; } [HttpGet, Route("zip")] public HttpResponseMessage DownloadZip() { var response = new HttpResponseMessage(); try { var zipFileName = string.Format("download_compressed_{0}.zip", DateTime.Now.ToString("yyyyMMddHHmmss")); var downloadDir = HttpContext.Current.Server.MapPath($"~/downloads/download"); var archive = $"{downloadDir}/{zipFileName}"; var temp = HttpContext.Current.Server.MapPath("~/downloads/temp"); // 清空临时文件夹中的所有临时文件 Directory.EnumerateFiles(temp).ToList().ForEach(File.Delete); ClearDownloadDirectory(downloadDir); // 生成新的临时文件 var counter = 1; foreach (var c in DemoData.GetMultiple) { var fileName = string.Format("each_file_{0}_{1}.txt", counter, DateTime.Now.ToString("yyyyMMddHHmmss")); if (c.Count <= 0) { continue; } var docPath = string.Format("{0}/{1}", temp, fileName); File.WriteAllLines(docPath, c, Encoding.UTF8); counter++; } Thread.Sleep(500); using (var zip = new ZipFile()) { // Make zip file zip.AddDirectory(temp); zip.Save(archive); } response.Content = new StreamContent(new FileStream(archive, FileMode.Open, FileAccess.Read)); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = zipFileName }; response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); } catch (Exception ex) { response.StatusCode = HttpStatusCode.InternalServerError; response.Content = new StringContent(ex.ToString()); } return response; } private void ClearDownloadDirectory(string directory) { var files = Directory.GetFiles(directory); foreach (var file in files) { try { File.Delete(file); } catch { } } } } }
到此,本示例的实现代码部分就完成了,如果我们此时打开地址:http://localhost:63161/download/single,浏览器会弹出保存文件的提示窗口,如下:
保存此文件后,打开它我们会看到我们的示例数据已被保存到本地了,如下:
同样的,下载压缩文件你只需要访问地址:localhost:63161/download/zip 即可,笔者就不再演示了。
最后,附上本示例项目的完整源代码,点击这里下载。
以上就是本文的全部内容,希望能给大家一个参考,也希望大家多多支持。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- [音展纪念碟]2006年《TAA台湾第十六届国际HI-ENDHI-FI音响展》2cd[WAV]
- 中国音乐地图之听见西藏山歌牧歌酒歌2020[WAV分轨]
- 王宏伟2017-永远的红飘带[太平洋影音][WAV+CUE]
- 费翔.1997-NOW现在【第一中国】【WAV+CUE】
- 新格合唱团.1981-我唱你和2辑(滚石新格民歌系列)【新格】【WAV+CUE】
- 陈柏宇.2011-QUINQUENNIUM【SONY】【WAV+CUE】
- 雨果唱片-《金唛系列-蔷薇依韵琼瑶》WAV
- 陈百强《凝望(2012华纳LPCD45限量版)[DMI]》[WAV整轨]
- 模拟之声慢刻CD《徐小凤45周年》[德国母带][低速原抓WAV+CUE]
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- 《王菲 单曲合集》[FlAC/分轨][520MB]
- 《费玉清 原味再现 水长流》[WAV+CUE][430MB]
- 群星.1992-畅销榜老歌金曲10CD【风格】【WAV+CUE】
- 孙悦.2024-时光音乐会【金蜂】【WAV+CUE】