一、类型介绍:
利用FileResult 我们可以将某个物理文件的内容响应给客户端;
返回类型FileResult(或FileContentResult 、FilePathResult 和 FileStramResult),执行方法为:File() --抽象类中重载了六个File方法,用于执行详细的操作;
二、FileResult内部结构
public abstract class FileResult : ActionResult
{
protected FileResult(string contentType);
public string ContentType { get; }
public string FileDownloadName { get; set; }
public override void ExecuteResult(ControllerContext context);
protected abstract void WriteFile(HttpResponseBase response); //在ExecuteResult方法中调用
}
ExecuteResult()方法具体实现:
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);
}
}
三、FileResult包含三个类型的FileResult子类:
分别是FileContentResult 、FilePathResult 和 FileStramResult
1.FileContentResult:
1.1 是针对文件(根据字节数组)内容创建的FileResult。
1.2 FileContentResult具有一个字节数组类型的只读属性FileContents,表示响应文件的内容,在构造函数中指定;
1.3 在抽象类Controller中重载定义了两个File方法,根据指定的字节数组、没提类型和下载文件名(可选)生成响应的FileContentResult,由于FileContentResult是根据字节数组创建
public abstract class Controller : ControllerBase
{
//其他成员
protected FileContentResult File(byte[] fileContents, string contentType);
protected virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName);
}
1.4 源码说明:
public class FileContentResult : FileResult
{
public byte[] FileContents { get; }
public FileContentResult(byte[] fileContents, string contentType);
protected override void WriteFile(HttpResponseBase response)
{
//先获得当前HttpResponse 的OutputStream 属性表示的输出流,然后调用其Write 方法直接将表示文件内容的字节数组进行输出。
response.OutputStream.Write(this.FileContents, 0, this.FileContents.Length);
}
}
1.5 使用环境:由于FileContentResult 是根据字节数组创建的,当我们需要动态生成响应文件内容〈而不是从物理文件中读取〉时, FileContentResult
是一个不错的选择。
2.FilePathResult
2.1. 是一个根据物理文件路径创建的FileResult;
2.2.通过源码分析:
public class FilePathResult : FileResult
{
public string FileName { get; }
public FilePathResult(string fileName , string contentType);
protected override void WriteFile(HttpResponseBase response)
{
response.TransmitFile(this.FileName); //将文件写入HTTP输出流
}
}
A.FileName属性:是一个只读属性,用于响应文件的路径,在构造函数中初始化;
B.WriteFile方法:直接将文件路径作为参数调用当前HttpResponseBase的TransmitFile方法实现了目标文件内容的输出;
C.抽象类Controller定义了两个File方法重载来根据文件路径创建相应的FilePathResult
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, ........
{
protected internal FilePathResult File(string fileName, string contentType);
protected internal virtual FilePathResult File(string fileName, string contentType, string fileDownloadName);
}
3.FileStreamResult
3.1.通过一个用于读取文件内容的Stream 对象来创建FileResult.
3.2.通过源码分析:
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, 0, 0x1000);
if (count == 0) { return; }
outputStream.Write(buffer, 0, count);
}
}
}
}
A.FileStream 属性:是一个只读属性,用于读取文件的Stream 对象,该属性在构造函数中被初始化;
B.WriteFile方法:通过指定的文件流读取文件内容,并最终调用当前HttpResponse 的OutputStream 属性的Write 方法将读取的内容写入
当前HTTP 响应的输出流中;
C.抽象类Controller 中同样定义了两个File 方法,它们重载根据文件读取的Stream 对象创建相应的FileStreamResult:
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, ........
{
protected internal FileStreamResult File(Stream fileStream, string contentType);
protected internal virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName);
}