一篇关于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 实现多文件打包并下载文件示例源码_转的更多相关文章

  1. 细说Asp.Net Web API消息处理管道(二)

    在细说Asp.Net Web API消息处理管道这篇文章中,通过翻看源码和实例验证的方式,我们知道了Asp.Net Web API消息处理管道的组成类型以及Asp.Net Web API是如何创建消息 ...

  2. ASP.NET Web API实践系列04,通过Route等特性设置路由

    ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...

  3. ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定

    本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...

  4. asp.net web api内部培训资料

    最近在公司进行了一次asp.net web api的分享吧,不算是培训. 可能大家有些人对Web API的推出目的还不是很了解,可以看看微软官方的定义,其实是为了提供一个好的REST Service方 ...

  5. ASP.NET Web API 文件產生器 - 使用 Swagger

    转帖:http://kevintsengtw.blogspot.hk/2015/12/aspnet-web-api-swagger.html Swagger 是一套 API 互動文件產生器,使用 HT ...

  6. 【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME

    原文:[ASP.NET Web API教程]5.3 发送HTML表单数据:文件上传与多部分MIME 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面 ...

  7. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  8. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

  9. ASP.NET Web API 控制器创建过程(一)

    ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...

随机推荐

  1. Spring第十一篇——–Spring整合Hibernate之配置数据源

    DataSource(数据源)提供了一个标准化的取得数据库连接的方式,通过getConnection()方法即可取得数据库的连接,Spring也提供了数据库连接池(DataBase connectio ...

  2. 修改了系统自带头文件后,Xcode会报错

    1.Xcode自带头文件的路径 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Develo ...

  3. Java基础之在窗口中绘图——绘制圆弧和椭圆(Sketcher 3 drawing arcs and ellipses)

    控制台程序. import javax.swing.JComponent; import java.util.*; import java.awt.*; import java.awt.geom.*; ...

  4. WebService之Axis2(4):二进制文件传输

    在<WebService大讲堂之Axis2(2):复合类型数据的传递>中讲过,如果要传递二进制文件(如图像.音频文件等),可以使用byte[]作为数据类型进行传递,然后客户端使用RPC方式 ...

  5. org.apache.ibatis.builder.IncompleteElementException: Could not find parameter map

    mybatis 出现这个错误是 参数类型写错了.parameterType 写成了parameterMap

  6. 删除NSMutableArray中的二维数组

    // 删除模型数据 [self.mutableArr[indexPath.section] removeObjectAtIndex:indexPath.row]; //删除UI(刷新数据,UI) [s ...

  7. PostgreSQL/bin

    pg_receivexlog pg_receivexlog—以流的方式从一个PostgreSQL集簇得到事务日志 pg_receivexlog被用来从一个运行着的PostgreSQL集簇以流的方式得到 ...

  8. Groupon面经Prepare: Max Cycle Length

    题目是遇到偶数/2,遇到奇数 *3 + 1的题目,然后找一个range内所有数字的max cycle length.对于一个数字,比如说44,按照题目的公式不停计算,过程是 44, 22, 11, 8 ...

  9. hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...

  10. poj: 1003

    简单题 #include <iostream> #include <stdio.h> #include <string.h> #include <stack& ...