ASP. net mvc understand the nature of FileResult, mvcfileresult
FileResult is a file-based ActionResult. With FileResult, we can easily return content from a physical file to the client. ASP. net mvc defines three specific FileResult types: FileContentResult, FilePathResult, and FileStreamResult. In this article, we will discuss how the three specific FileResult Methods respond to requests.
I. FileResult
As shown in the following code snippet, FileResult has a read-only attribute ContentType indicating the media type, which is initialized in the constructor. The corresponding media type is "image/pdf". For a file, "application/pdf" is used ".
Public abstract class FileResult: ActionResult {private string _ fileDownloadName; protected FileResult (string contentType) {if (string. isNullOrEmpty (contentType) {throw new ArgumentException (MvcResources. common_NullOrEmpty, "contentType");} this. contentType = contentType;} public override void ExecuteResult (ControllerContext context) {if (context = null) {throw new ArgumentNullException ("c Ontext ") ;}httpresponsebase response = context. HttpContext. Response; response. ContentType = this. ContentType; if (! String. isNullOrEmpty (this. fileDownloadName) {string headerValue = ContentDispositionUtil. getHeaderValue (this. fileDownloadName); context. httpContext. response. addHeader ("Content-Disposition", headerValue);} this. writeFile (response);} protected abstract void WriteFile (HttpResponseBase response); public string ContentType {get; private set;} public string FileDownloadName {get {return (this. _ fi LeDownloadName ?? String. empty);} set {this. _ fileDownloadName = value ;}} internal static class ContentDispositionUtil {private const string HexDigits = "0123456789 ABCDEF"; private static void AddByteToStringBuilder (byte B, StringBuilder builder) {builder. append ('%'); int num = B; AddHexDigitToStringBuilder (num> 4, builder); AddHexDigitToStringBuilder (num % 0x10, builder );} private static void AddHexDigitToStringBuilder (int digit, StringBuilder builder) {builder. append ("0123456789 ABCDEF" [digit]);} private static string CreateRfc2231HeaderValue (string filename) {StringBuilder builder = new StringBuilder ("attachment; filename * = UTF-8 ''"); foreach (byte num in Encoding. UTF8.GetBytes (filename) {if (IsByteValidHeaderValueCharacter (num) {builder. append (char) num);} else {AddByteToStringBuilder (num, builder);} return builder. toString ();} public static string GetHeaderValue (string fileName) {foreach (char ch in fileName) {if (ch> '\ x007f') {return CreateRfc2231HeaderValue (fileName );}} contentDisposition disposition = new ContentDisposition {FileName = fileName}; return disposition. toString ();} private static bool IsByteValidHeaderValueCharacter (byte B) {if (0x30 <= B) & (B <= 0x39) {return true ;} if (0x61 <= B) & (B <= 0x7a) {return true;} if (0x41 <= B) & (B <= 90) {return true;} switch (B) {case 0x3a: case 0x5f: case 0x7e: case 0x24: case 0x26: case 0x21: case 0x2b: case 0x2d: case 0x2e: return true ;}return false ;}}}View Code
There are two types of responses to files: Inline and Attachment ). In general, the former will use a browser to directly open the response file, while the latter will download it to the client as an independent file. For the latter, we usually specify a file name for the downloaded file, which can be specified through the FileResult FileDownloadName attribute. File responses adopt the inline method by default. If you need to adopt the attachment Form, you need to create a header named Content-Disposition for the response. The format of the header value is "attachment; filename = {FileDownloadName }".
FileResult is just an abstract class. The output of file content is implemented in the abstract method WriteFile. This method is called in the rewritten ExecuteResult method. If the FileDownloadName attribute is not empty, file response is performed in the form of attachments. FileResult sets the Content-Disposition response header in the rewritten ExecuteResult method. The following code snippets basically reflect the implementation of the ExecuteResult method in FileResult.
public override void ExecuteResult(ControllerContext context){ if (context == null) { throw new ArgumentNullException("context"); } HttpResponseBase response = context.HttpContext.Response; response.ContentType = this.ContentType; if (!string.IsNullOrEmpty(this.FileDownloadName)) { string headerValue = ContentDispositionUtil.GetHeaderValue(this.FileDownloadName); context.HttpContext.Response.AddHeader("Content-Disposition", headerValue); } this.WriteFile(response);}
ASP. net mvc defines three specific FileResult types: FileContentResult, FilePathResult, and FileStreamResult. Next we will introduce them separately.
Ii. FileContentResult
FileContentResult is the FileResult created for the file content. As shown in the following code snippet, FileContentResult has a read-only attribute of the byte array type. FileContents indicates the content of the response file, which is specified in the constructor. The implementation of FileContentResult's response to the file content is also very simple, as can be seen from the WriteFile method definition shown below, it only calls the Write method of the OutputStream attribute of the current HttpResponse to directly Write the byte array representing the file content to the response output stream.
public class FileContentResult : FileResult{ public FileContentResult(byte[] fileContents, string contentType) : base(contentType) { if (fileContents == null) { throw new ArgumentNullException("fileContents"); } this.FileContents = fileContents; } protected override void WriteFile(HttpResponseBase response) { response.OutputStream.Write(this.FileContents, 0, this.FileContents.Length); } public byte[] FileContents { get; private set; }}
public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IController, IAsyncManagerContainer{ protected internal FileContentResult File(byte[] fileContents, string contentType) { return this.File(fileContents, contentType, null); } protected internal virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName) { return new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName }; }}
The abstract class Controller defines the above two File overloading to generate the corresponding FileContentResult Based on the specified byte array, media type, and download File name (optional. Because FileContentResult is created based on the byte array, FileContentResult is a good choice when we need to dynamically generate the response file content (instead of reading from the physical file.
3. FilePathResult
From the name, we can see that FilePathResult is a file created based on the physical file path. As shown in the following code snippet, the path of the response file is represented by the read-only attribute FileName, Which is initialized in the constructor. In the implemented WriteFile method, FilePathResult directly uses the file path as a parameter to call the current HttpResponse TransmitFile to implement the response to the file content. The abstract class Controller also defines two File method overloading to create the corresponding FilePathResult Based on the File path.
public class FilePathResult : FileResult{ public FilePathResult(string fileName, string contentType) : base(contentType) { if (string.IsNullOrEmpty(fileName)) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "fileName"); } this.FileName = fileName; } protected override void WriteFile(HttpResponseBase response) { response.TransmitFile(this.FileName); } public string FileName { get; private set; }}
public abstract class Controller : ControllerBase,...{ protected internal FilePathResult File(string fileName, string contentType) { return this.File(fileName, contentType, null); } protected internal virtual FilePathResult File(string fileName, string contentType, string fileDownloadName) { return new FilePathResult(fileName, contentType) { FileDownloadName = fileDownloadName }; } .....}
Iv. FileStreamResult
FileStreamResult allows us to create a FileResult through a stream used to read the file content. As shown in the following code snippet, the read-only attribute FileStream indicates that the attribute is initialized in the constructor. In the WriteFile method, FileStreamResult reads the file content through the specified file stream, finally, the Write method of the OutputStream attribute of the current HttpResponse is called to Write the read content to the output stream of the current HTTP response. The abstract class Controller also defines two File method overloading to create the corresponding FileStreamResult Based on the File read stream.
public class FileStreamResult : FileResult{ private const int BufferSize = 0x1000; public FileStreamResult(Stream fileStream, string contentType) : base(contentType) { if (fileStream == null) { throw new ArgumentNullException("fileStream"); } this.FileStream = fileStream; } 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); } } } public Stream FileStream { get; private set; }}
public abstract class Controller : ControllerBase, ...{ protected internal FileStreamResult File(Stream fileStream, string contentType) { return this.File(fileStream, contentType, null); } protected internal virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName) { return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; } ...}
This article is a record from instructor Jiang's understanding of the nature of several actionresults of ASP. net mvc: FileResult