一篇关于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. ionic 报错%1 is not a valid Win32 application

    Fixed the problem by installing python version 3.0 and above will do下载Python3.0或以上版本 python官网传送门:htt ...

  2. SQLAlchemy 对象缓存和刷新

    SQLAlchemy 对象缓存和刷新 SQLAlchemy 带有对象缓存机制,在重复查询相同的对象时,直接先查询本地的缓存,而不需要从数据库加载数据. 在每个 model 对象的内部,SQLAlche ...

  3. wordpress 天气插件开发

    <?php /* * author by:wordpress教程网(http://www.wpnoob.cn) * url: * */ class weatherWidget extends W ...

  4. Highcharts动态赋值学习

    最近老大让做项目中的统计图表功能,需要使用highcharts这个插件,弄出来了两种类型的图表动态赋值的实现,首先贴上中文网的官网和api地址,使用这个英语不好的同学肯定会用到的: 中文网官网:htt ...

  5. myeclipse中的web项目导入到eclipse中注意事项,项目部署到tomcat后无法访问jsp文件

    打开eclipse,点击空白处,右键可以看到import>general>existing projects into workspace>next>选择你的myeclipse ...

  6. News: Visual Studio Code support debugging Linux Apps

    http://arstechnica.com/information-technology/2015/11/visual-studio-now-supports-debugging-linux-app ...

  7. log4cxx安装和使用

    log4cxx是Java社区著名的log4j的c++移植版,用于为C++程序提供日志功能,以便开发者对目标程序进行调试和审计,log4cxx是apache软件基金会的开源项目,基于APR实现跨平台支持 ...

  8. PostgreSQL Replication之第十二章 与Postgres-XC一起工作(3)

    12.3 配置一个简单的集群 在本章中,我们要建立一个由三个数据节点组成的集群.一个协调节点,以及管理集群的全局事务管理节点.对于每个组件,我们必须创建一个目录: hs@vm:~/data$ ls - ...

  9. Leetcode: Guess Number Higher or Lower

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  10. G面经prepare: Chucked Palindrome

    给定一个字符串,找出最多有多少个chunked palindrome, 正常的palindrome是abccba, chunked palindrome的定义是:比如volvo, 可以把vo划分在一起 ...