Asp.Net Web Api 2 实现多文件打包并下载文件示例源码_转
一篇关于Asp.Net Web Api下载文件的文章,之前我也写过类似的文章,请见:《ASP.NET(C#) Web Api通过文件流下载文件到本地实例》
本文以这篇文章的基础,提供了ByteArrayContent的下载以及在下载多个文件时实现在服务器对多文件进行压缩打包后下载的功能。
关于本文中实现的在服务器端用.NET压缩打包文件功能的过程中,使用到了一个第方类库:DotNetZip,具体的使用将在正文中涉及。好了,描述了这么多前言,下面我们进入本文示例的正文。
一、创建项目
1.1 首先创建名为:WebApiDownload的Web Api 项目(C#);
1.2 接着新建一个空的控制器,命名为:DownloadController;
1.3 创建一些打包文件和存放临时文件的文件夹(downloads),具体请看本文最后提供的示例项目代码
1.4 打开NuGet程序包管事器,搜索DotNetZip,如下图:
搜索到DotNetZip安装包后,进行安装,以便用于本项目将要实现多文件打包压缩的功能,如下图:
安装完成DotNetZip包后,我们就可以退出NuGet程序包管理器了,因为本项目为示例项目,不需再添加其他的包。
1.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 <= )
{
Contacts.Add(File1);
Contacts.Add(File2);
Contacts.Add(File3);
}
return Contacts;
}
}
}
}
1.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 = ;
foreach (var c in DemoData.GetMultiple)
{
var fileName = string.Format("each_file_{0}_{1}.txt", counter, DateTime.Now.ToString("yyyyMMddHHmmss"));
if (c.Count <= )
{
continue;
}
var docPath = string.Format("{0}/{1}", temp, fileName);
File.WriteAllLines(docPath, c, Encoding.UTF8);
counter++;
}
Thread.Sleep();
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
{
}
}
}
}
}
二、运行示例
2.1 到此,本示例的实现代码部分就完成了,如果我们此时打开地址:http://localhost:63161/download/single,浏览器会弹出保存文件的提示窗口,如下:
2.2 保存此文件后,打开它我们会看到我们的示例数据已被保存到本地了,如下:
文章:Asp.Net Web Api 2利用ByteArrayContent和StreamContent分别实现下载文件示例源码(含多文件压缩功能)
Asp.Net Web Api 2 实现多文件打包并下载文件示例源码_转的更多相关文章
- 细说Asp.Net Web API消息处理管道(二)
在细说Asp.Net Web API消息处理管道这篇文章中,通过翻看源码和实例验证的方式,我们知道了Asp.Net Web API消息处理管道的组成类型以及Asp.Net Web API是如何创建消息 ...
- ASP.NET Web API实践系列04,通过Route等特性设置路由
ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...
- ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定
本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...
- asp.net web api内部培训资料
最近在公司进行了一次asp.net web api的分享吧,不算是培训. 可能大家有些人对Web API的推出目的还不是很了解,可以看看微软官方的定义,其实是为了提供一个好的REST Service方 ...
- ASP.NET Web API 文件產生器 - 使用 Swagger
转帖:http://kevintsengtw.blogspot.hk/2015/12/aspnet-web-api-swagger.html Swagger 是一套 API 互動文件產生器,使用 HT ...
- 【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME
原文:[ASP.NET Web API教程]5.3 发送HTML表单数据:文件上传与多部分MIME 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面 ...
- 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用
由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...
- ASP.NET Web API 控制器创建过程(二)
ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...
- ASP.NET Web API 控制器创建过程(一)
ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...
随机推荐
- JavaScript基础总结三部曲之一
JavaScript是一种基于对象的编程语言,基于对象指的是所有的对象已经由浏览器提供好了,用户直接使用就可以了. 另外,JS是嵌入在HTML语法之中的编程语言. PS:虽然是基于对象的语言,但是 ...
- python3学习问题汇总
1.python2脚本转python3报类型错误 TypeError: ‘str’ does not support the buffer interface 原因:Python3x的string类型 ...
- Power-BI 仪表盘实现动态预警
BI系统中仪表盘“序列”中的“预警”属性可以手工填入固定的值,也可从数据集里取值设定预警范围 ,以实现动态预警.其中的“范围”属性手工输入固定值应该为百分比(0-1),而在下拉选择绑定列为值是为数值. ...
- shell中如何判断某一命令是否存在
参考: http://www.cnblogs.com/tuzkee/p/3755230.html https://segmentfault.com/q/1010000000156870 http:// ...
- sublime 垂直编辑
http://www.sublimetext.com/docs/2/multiple_selection_with_the_keyboard.html
- python实现跳板机
公司有1000多台服务器,线上机器都是禁止root登录的,所以平时是用普通用户登录,然后在su到root,密码都是在excel表中存的,这样登录一台机器,输两次命令,搜两次密码,实在很麻烦,有一天备份 ...
- MySQL复制-设置延迟复制
mysql> stop slave ; Query OK, 0 rows affected (0.00 sec) mysql> change master to master_delay= ...
- MongoDB分片集群还原
从mongodb 3.0开始,mongorestore还原的时候,需要一个运行着的实例.早期的版本没有这个要求. 1.为每个分片部署一个复制集 (1)复制集中的每个成员启动一个mongod mongo ...
- DataGridView的单元格控制只能输入数字
主要是应用DataGridView的EditingControlShowing事件.当单元格进入编辑模式时,可以处理执行该编辑控件的自定义初始化的此事件. public DataGridViewTex ...
- 连接sql server数据库的两种方式
class DB { private static SqlConnection conn; public static SqlConnection getConn() { //conn = n ...