了解ASP.NET MVC几种ActionResult的本质:FileResult

FileResult是一个基于文件的ActionResult,利用FileResult我们可以很容易地将从某个物理文件的内容响应给客 户端。ASP.NET MVC定义了三个具体的FileResult,分别是FileContentResult、FilePathResult和 FileStreamResult。在这篇文章中我们将探讨三种具体的FileResult是如何将文件内容对请求进行响应的。
一、FileResult
如 下面的代码片断所示,FileResult具有一个表示媒体类型的只读属性ContentType,该属性在构造函数中被初始化。当我们基于某个物理文件 创建相应的FileResult对象的时候应该根据文件的类型指定媒体类型,比如说目标文件是一个.jpg图片,那么对应的媒体类型为 “image/jpeg”,对于一个.pdf文件,则采用“application/pdf”。

双击代码全选

1

1:publicabstractclass FileResult : ActionResult

 

双击代码全选

1

2: {

 

双击代码全选

1

3:protected FileResult(string contentType);

 

双击代码全选

1

4:publicoverridevoid ExecuteResult(ControllerContext context);

 

双击代码全选

1

5:protectedabstractvoid WriteFile(HttpResponseBase response);

 

双击代码全选

1

 

 

双击代码全选

1

7:publicstring ContentType { get; }

 

双击代码全选

1

8:publicstring FileDownloadName { get; set; }

 

双击代码全选

1

9: }

 

针 对文件的响应具有两种形式,即内联(Inline)和附件(Attachment)。一般来说,前者会利用浏览器直接打开响应的文件,而后者会以独立的文 件下载到客户端。对于后者,我们一般会为下载的文件指定一个文件名,这个文件名可以通过FileResult的FileDownloadName属性来指 定。文件响应在默认情况下采用内联的方式,如果需要采用附件的形式,需要为响应创建一个名称为Content-Disposition的报头,该报头值的 格式为“attachment; filename={ FileDownloadName }”。
FileResult仅仅是一个抽象 类,文件内容的输出实现在抽象方法WriteFile中,该方法会在重写的ExecuteResult方法中调用。如果FileDownloadName 属性不为空,意味着会采用附件的形式进行文件响应,FileResult会在重写的ExecuteResult方法中进行Content- Disposition响应报头的设置。如下面的代码片断基本上体现了ExecuteResult方法在FileResult中的实现。

双击代码全选

1

1:publicabstractclass FileResult : ActionResult

 

双击代码全选

1

2: {

 

双击代码全选

1

3://其他成员

 

双击代码全选

1

4:publicoverridevoid ExecuteResult(ControllerContext context)

 

双击代码全选

1

5:     {

 

双击代码全选

1

6:         HttpResponseBase response = context.HttpContext.Response;

 

双击代码全选

1

7:         response.ContentType = this.ContentType;

 

双击代码全选

1

8:if (!string.IsNullOrEmpty(this.FileDownloadName))

 

双击代码全选

1

9:         {

 

双击代码全选

1

10://生成Content-Disposition响应报头值

 

双击代码全选

1

11:string headerValue = ContentDispositionUtil.GetHeaderValue(this.FileDownloadName);

 

双击代码全选

1

12:             context.HttpContext.Response.AddHeader("Content-Disposition", headerValue);

 

双击代码全选

1

13:         }

 

双击代码全选

1

14:this.WriteFile(response);

 

双击代码全选

1

15:     }

 

双击代码全选

1

16: }

 

ASP.NET MVC定义了三个具体的FileResult,分别是FileContentResult、FilePathResult和FileStreamResult,接下来我们对它们进行单独介绍。

二、FileContentResult

FileContentResult 是针对文件内容创建的FileResult。如下面的代码片断所示,FileContentResult具有一个字节数组类型的只读属性 FileContents表示响应文件的内容,该属性在构造函数中指定。FileContentResult针对文件内容的响应实现也很简单,从如下所示 的WriteFile方法定义可以看出,它只是调用当前HttpResponse的OutputStream属性的Write方法直接将表示文件内容的字 节数组写入响应输出流。

双击代码全选

1

1:publicclass FileContentResult : FileResult

 

双击代码全选

1

2: {

 

双击代码全选

1

3:publicbyte[] FileContents { get; }

 

双击代码全选

1

4:public FileContentResult(byte[] fileContents, string contentType) ;

 

双击代码全选

1

 

 

双击代码全选

1

6:protectedoverridevoid WriteFile(HttpResponseBase response)

 

双击代码全选

1

7:     {

 

双击代码全选

1

8:         response.OutputStream.Write(this.FileContents, 0, this.FileContents.Length);

 

双击代码全选

1

9:     }

 

双击代码全选

1

10: }

 

双击代码全选

1

11:

 

双击代码全选

1

12:publicabstractclass Controller : ControllerBase, ...

 

双击代码全选

1

13: {

 

双击代码全选

1

14:// 其他成员

 

双击代码全选

1

15:protected FileContentResult File(byte[] fileContents, string contentType);

 

双击代码全选

1

16:protectedvirtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName);

 

双击代码全选

1

17: }

 

抽 象类Controller中定义了如上两个File重载根据指定的字节数组、媒体类型和下载文件名(可选)生成相应的 FileContentResult。由于FileContentResult是根据字节数组创建的,当我们需要动态生成响应文件内容(而不是从物理文件 中读取)时,FileContentResult是一个不错的选择。

三、FilePathResult

从名称可以看 出,FilePathResult是一个根据物理文件路径创建FileResult。如下面的代码片断所示,表示响应文件的路径通过只读属性 FileName表示,该属性在构造函数中被初始化。在实现的WriteFile方法中,FilePathResult直接将文件路径作为参数调用当前 HttpResponse的TransmitFile实现了针对文件内容的响应。抽象类Controller同样定义了两个File方法重载来根据文件路 径创建相应的FilePathResult。

双击代码全选

1

1:publicclass FilePathResult : FileResult

 

双击代码全选

1

2: {

 

双击代码全选

1

3:publicstring FileName { get; }

 

双击代码全选

1

4:public FilePathResult(string fileName, string contentType);

 

双击代码全选

1

 

 

双击代码全选

1

6:protectedoverridevoid WriteFile(HttpResponseBase response)

 

双击代码全选

1

7:     {

 

双击代码全选

1

8:         response.TransmitFile(this.FileName);

 

双击代码全选

1

9:     }

 

双击代码全选

1

10: }

 

双击代码全选

1

11:

 

双击代码全选

1

12:publicabstractclass Controller : ControllerBase, ...

 

双击代码全选

1

13: {

 

双击代码全选

1

14://其他成员

 

双击代码全选

1

15:protected FilePathResult File(string fileName, string contentType);

 

双击代码全选

1

16:protectedvirtual FilePathResult File(string fileName, string contentType, string fileDownloadName);

 

双击代码全选

1

17: }