ASP.Net MVC 之FileResult
FileResult是一个基于文件的ActionResult,利用FileResult我们可以很容易地将从某个物理文件的内容响应给客户端。ASP.NET MVC定义了三个具体的FileResult,分别是FileContentResult、FilePathResult和FileStreamResult。在这篇文章中我们将探讨三种具体的FileResult是如何将文件内容对请求进行响应的。[本文已经同步到《How ASP.NET MVC Works?》中]
目录
一、FileResult
二、FileContentResult
三、FilePathResult
四、FileStreamResult
五、实例演示:通过FileResult发布图片
一、FileResult
如下面的代码片断所示,FileResult具有一个表示媒体类型的只读属性ContentType,该属性在构造函数中被初始化。当我们基于某个物理文件创建相应的FileResult对象的时候应该根据文件的类型指定媒体类型,比如说目标文件是一个.jpg图片,那么对应的媒体类型为“image/jpeg”,对于一个.pdf文件,则采用“application/pdf”。
public abstract class FileResult : ActionResult
{
protected FileResult(string contentType);
public override void ExecuteResult(ControllerContext context);
protected abstract void WriteFile(HttpResponseBase response); public string ContentType { get; }
public string FileDownloadName { get; set; }
}
针对文件的响应具有两种形式,即内联(Inline)和附件(Attachment)。一般来说,前者会利用浏览器直接打开响应的文件,而后者会以独立的文件下载到客户端。对于后者,我们一般会为下载的文件指定一个文件名,这个文件名可以通过FileResult的FileDownloadName属性来指定。文件响应在默认情况下采用内联的方式,如果需要采用附件的形式,需要为响应创建一个名称为Content-Disposition的报头,该报头值的格式为“attachment; filename={ FileDownloadName }”。
FileResult仅仅是一个抽象类,文件内容的输出实现在抽象方法WriteFile中,该方法会在重写的ExecuteResult方法中调用。如果FileDownloadName属性不为空,意味着会采用附件的形式进行文件响应,FileResult会在重写的ExecuteResult方法中进行Content-Disposition响应报头的设置。如下面的代码片断基本上体现了ExecuteResult方法在FileResult中的实现。
public abstract class FileResult : ActionResult
{
//其他成员
public override void ExecuteResult(ControllerContext context)
{
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = this.ContentType;
if (!string.IsNullOrEmpty(this.FileDownloadName))
{
//生成Content-Disposition响应报头值
string headerValue = ContentDispositionUtil.GetHeaderValue(this.FileDownloadName);
context.HttpContext.Response.AddHeader("Content-Disposition", headerValue);
}
this.WriteFile(response);
}
}
ASP.NET MVC定义了三个具体的FileResult,分别是FileContentResult、FilePathResult和FileStreamResult,接下来我们对它们进行单独介绍。
二、FileContentResult
FileContentResult是针对文件内容创建的FileResult。如下面的代码片断所示,FileContentResult具有一个字节数组类型的只读属性FileContents表示响应文件的内容,该属性在构造函数中指定。FileContentResult针对文件内容的响应实现也很简单,从如下所示的WriteFile方法定义可以看出,它只是调用当前HttpResponse的OutputStream属性的Write方法直接将表示文件内容的字节数组写入响应输出流。
public class FileContentResult : FileResult
{
public byte[] FileContents { get; }
public FileContentResult(byte[] fileContents, string contentType) ; protected override void WriteFile(HttpResponseBase response)
{
response.OutputStream.Write(this.FileContents, , this.FileContents.Length);
}
} public abstract class Controller : ControllerBase, ...
{
// 其他成员
protected FileContentResult File(byte[] fileContents, string contentType);
protected virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName);
}
抽象类Controller中定义了如上两个File重载根据指定的字节数组、媒体类型和下载文件名(可选)生成相应的FileContentResult。由于FileContentResult是根据字节数组创建的,当我们需要动态生成响应文件内容(而不是从物理文件中读取)时,FileContentResult是一个不错的选择。
三、FilePathResult
从名称可以看出,FilePathResult是一个根据物理文件路径创建FileResult。如下面的代码片断所示,表示响应文件的路径通过只读属性FileName表示,该属性在构造函数中被初始化。在实现的WriteFile方法中,FilePathResult直接将文件路径作为参数调用当前HttpResponse的TransmitFile实现了针对文件内容的响应。抽象类Controller同样定义了两个File方法重载来根据文件路径创建相应的FilePathResult。
public class FilePathResult : FileResult
{
public string FileName { get; }
public FilePathResult(string fileName, string contentType); protected override void WriteFile(HttpResponseBase response)
{
response.TransmitFile(this.FileName);
}
} public abstract class Controller : ControllerBase, ...
{
//其他成员
protected FilePathResult File(string fileName, string contentType);
protected virtual FilePathResult File(string fileName, string contentType, string fileDownloadName);
}
四、FileStreamResult
FileStreamResult允许我们通过一个用于读取文件内容的流来创建FileResult。如下面的代码片断所示,读取文件流通过只读属性FileStream表示,该属性在构造函数中被初始化。在实现的WriteFile方法中,FileStreamResult通过指定的文件流读取文件内容,并最终调用当前HttpResponse的OutputStream属性的Write方法将读取的内容写入当前HTTP响应的输出流中。抽象类Controller中同样定义了两个File方法重载根据文件读取流创建相应的FileStreamResult。
public class FileStreamResult : FileResult
{
public Stream FileStream { get; }
public FileStreamResult(Stream fileStream, string contentType); protected override void WriteFile(HttpResponseBase response)
{
Stream outputStream = response.OutputStream;
using (this.FileStream)
{
byte[] buffer = new byte[0x1000];
while (true)
{
int count = this.FileStream.Read(buffer, , 0x1000);
if (count == )
{
return;
}
outputStream.Write(buffer, , count);
}
}
}
}
public abstract class Controller : ControllerBase, ...
{
//其他成员
protected FileStreamResult File(Stream fileStream, string contentType);
protected virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName);
}
五、实例演示:通过FileResult发布图片
为了让读者对FileResult具有更加深刻地认识,我们通过一个实例来演示如何通过FileResult来对外发布图片。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中,我们在根目录下添加一个名为images的子目录来存放发布的.jpg图片,然后我们定义如下一个HomeController。
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
} public ActionResult Image(string id)
{
string path = Server.MapPath("/images/" + id + ".jpg");
return File(path, "image/jpeg");
}
}
图片的发布体现在Action方法Image上,表示图片ID的参数同时作为图片的文件名(不含扩展名)。在该方法中,我们根据图片ID解析出对应文件的路径后,直接调用File方法创建一个媒体类型为“image/jpeg”的FilePathResult。在Action方法Index中呈现的View定义如下,我们通过一个列表显示6张图片。基于图片的<img>元素的src属性指定的地址正是指向定义在HomeController的Action方法Image,指定的表示图片ID的参数分别是001、002、…、006。
<html>
<head>
<title>Gallery</title>
<style type = "text/css" >
li{list-style-type:none; float:left; margin:10px 10px 0px 0px;}
img{width:100px; height:100px;}
</style>
</head>
<body>
<ul>
<li><img alt = "001" src="@Url.Action("Image", new { id = "001" })"/></li>
<li><img alt = "002" src="@Url.Action("Image", new { id = "002" })"/></li>
<li><img alt = "003" src="@Url.Action("Image", new { id = "003" })"/></li>
<li><img alt = "004" src="@Url.Action("Image", new { id = "004" })"/></li>
<li><img alt = "005" src="@Url.Action("Image", new { id = "005" })"/></li>
<li><img alt = "006" src="@Url.Action("Image", new { id = "006" })"/></li>
</ul>
</body>
</html>
我们将6张.jpg图片存放到/imges目录下,并分别命名为001、002、…、006。
ASP.Net MVC 之FileResult的更多相关文章
- ASP.NET MVC 了解FileResult的本质
FileResult是一个基于文件的ActionResult,利用FileResult我们可以很容易地将从某个物理文件的内容响应给客户端.ASP.NET MVC定义了三个具体的FileResult,分 ...
- Asp.Net MVC 使用FileResult导出Excel数据文件
MVC实现Excel导出功能,今天来记录一下. 采取了最简单的方法.(转载) 用的是Html拼接成Table表格的方式,返回 FileResult 输出一个二进制的文件. 第一种:使用FileCo ...
- Asp.Net Mvc表单提交之List集合
一.说明 1.Asp.Net Mvc中Action的参数可以自动接收和反序列化form表单的值, 2.对于name=value类型,只要Action参数的变量名和input的name相同就行,不区分大 ...
- ASP.net MVC 文件下载的几种方法(欢迎讨论)
在ASP.net MVC 中有几种下载文件的方法 前提:要下载的文件必须是在服务器目录中的,至于不在web项目server目录中的文件下载我不知道,但是还挺想了解的. 第一种:最简单的超链接方法,&l ...
- 漫步ASP.NET MVC的处理管线
ASP.NET MVC从诞生到现在已经好几个年头了,这个框架提供一种全新的开发模式,更符合web开发本质.你可以很好的使用以及个性化和扩展这个框架,但这需要你对它有足够的了解.这篇文章主要从整体角度总 ...
- 【读书笔记】Asp.Net MVC 上传图片到数据库(会的绕行)
之前上传图片的做法都是上传到服务器上的文件夹中,再将url保存到数据库.其实在MVC中将图片上传到数据库很便捷的事情,而且不用去存url了.而且这种方式支持ie6(ie6不支持jquery自动提交fo ...
- [ASP.NET MVC 小牛之路]09 - Controller 和 Action (1)
我们知道,在 MVC 中每个请求都会提交到 Controller 进行处理.Controller 是和请求密切相关的,它包含了对请求的逻辑处理,能对 Model 进行操作并选择 View 呈现给用户, ...
- 新作《ASP.NET MVC 5框架揭秘》正式出版
ASP.NET MVC是一个建立在ASP.NET平台上基于MVC模式的Web开发框架,它提供了一种与Web Form完全不同的开发方式.ASP.NET Web Form借鉴了Windows Form基 ...
- 微信扫码支付+Asp.Net MVC
这里的扫码支付指的是PC网站上面使用微信支付,也就是官方的模式二,网站是Asp.net MVC,整理如下.(demo在最下方) 一.准备工作 使用的微信API中的统一下单方法,关键的参数是‘公众账号I ...
随机推荐
- Rabbitmq init terminating in do boot 问题
其实出现这个问题的原因很简单,就是rabbitmq的安装目录中是不能带空格的,但是官方安装包会默认的将我们的程序安装到Program Files下,哭晕啊有没有.所以,我们将rabbitmq从D:\P ...
- $().change事件
change([[data],fn]) 当元素的value值发生改变时发生change事件 适用于: 文本域 text textarea和select元素 text textarea 元素失去焦点时发 ...
- 转:Python 与 Excel 不得不说的事
数据处理是 Python 的一大应用场景,而 Excel 则是最流行的数据处理软件.因此用 Python 进行数据相关的工作时,难免要和 Excel 打交道. 如果仅仅是要以表单形式保存数据,可以借助 ...
- 【leetcode】62. Uniqe Paths
题目 https://oj.leetcode.com/problems/unique-paths/ A robot is located at the top-left corner of a m ...
- python之7-2类的继承与多态
类的继承的意思就如同父子关系一样,这个儿子继承了父亲的一切,但是在某些地方(属性)相同的时候,儿子的属性大于老子的属性(覆盖),最底层类,总会继承最接近它的那个类的属性init 类的多态总是和继承相连 ...
- HDU-1799(组合递推公式)
HDOJ-1799 - Fighting_Dream M - 暴力求解.打表 Time Limit:1000MS Memory Limit:32768KB 64bit IO Forma ...
- iOS编程修改系统音量
iOS的AVFoundation框架提供了基本的音视频播放工具,我们基本上可以靠其中提供的类完成绝大部分的音视频播放任务.但是在音频播放的输出音量的处理上,苹果的策略比较保守.尽管AVPlayer和A ...
- C语言学习--可变数组
#ifndef _ARRAY_ #define _ARRAY_ typedef struct { int *array; int size; } Array; //此处定义结构数据类型 Array,虽 ...
- java四种创建对象的方法
1.用new语句创建对象,这是最常见的创建对象的方法. 2.运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance ...
- MyEclipse10 中增加svn插件
http://www.cnblogs.com/bluesky4485/archive/2012/04/23/2467177.html 确实这种方法可行!向牛人学习!