1. 程式人生 > >ASP.NET Core應用針對靜態檔案請求的處理[3]: StaticFileMiddleware中介軟體如何處理針對檔案請求

ASP.NET Core應用針對靜態檔案請求的處理[3]: StaticFileMiddleware中介軟體如何處理針對檔案請求

我們通過《以Web的形式釋出靜態檔案》和《條件請求與區間請求》中的例項演示,以及上面針對條件請求和區間請求的介紹,從提供的功能和特性的角度對這個名為StaticFileMiddleware的中間進行了全面的介紹,接下來我們將更近一步,將從實現原理的角度來進一步認識這個中介軟體。 [本文已經同步到《ASP.NET Core框架揭祕》之中]

目錄
一、StaticFileMiddleware
二、ContentTypeProvider
三、利用配置指定StaticFileOptions
四、實現原理

一、StaticFileMiddleware

不過在此之前,我們先來看看StaticFileMiddleware這個型別的定義。

   1: public class StaticFileMiddleware
   2: {
   3:     public StaticFileMiddleware(RequestDelegate next, IHostingEnvironment hostingEnv, IOptions<StaticFileOptions> options, ILoggerFactory loggerFactory);
   4:     public Task Invoke(HttpContext context);
   5: }

如上面的程式碼片段所示,除了作為“下一個中介軟體”的next引數之前,StaticFileMiddleware的建構函式還包含三個引數。其中hostingEnv和loggerFactory這兩個引數分別表示當前執行環境和用來建立Logger的工廠,最重要的options引數表示為這個中介軟體指定的配置選項,至於具體可以提供怎樣的配置選項,我們只需要看看 StaticFileOptions

這個型別提供了怎樣的屬性成員。

   1: public class StaticFileOptions : SharedOptionsBase
   2: {
   3:     public IContentTypeProvider                  ContentTypeProvider { get; set; }
   4:     public string                                DefaultContentType { get; set; }
   5:     public bool                                  ServeUnknownFileTypes { get; set; }
   6:     public Action<StaticFileResponseContext>     OnPrepareResponse { get; set; }    
   7:  
   8:     public StaticFileOptions();
   9:     public StaticFileOptions(SharedOptions sharedOptions);
  10: }
  11:  
  12: public abstract class SharedOptionsBase
  13: {
  14:     protected SharedOptionsBase(SharedOptions sharedOptions);
  15:     public IFileProvider     FileProvider { get; set; }
  16:     public PathString        RequestPath { get; set; }
  17: }
  18:  
  19: public class SharedOptions
  20: {
  21:     public IFileProvider     FileProvider { get; set; }
  22:     public PathString        RequestPath { get; set; }
  23: }
  24:  
  25: public class StaticFileResponseContext
  26: {
  27:     public HttpContext       Context { get; }
  28:     public IFileInfo         File { get; }
  29: }

如上面的程式碼片段所示,StaticFileOptions繼承自抽象型別SharedOptionsBase,後者實際上體現的是兩個路徑之間的對映關係,一個是HTTP請求採用的路徑,另一個則是檔案的實體地址,後者體現為一個FileProvider物件。不過也正是因為檔案的讀取是通過這個FileProvider來完成的,而FileProvider未必就一定對應著具體的物理檔案,所以StaticFileMiddleware並不限於針對專門處理“物理檔案”。

直接定義在StaticFileOptions中的前三個型別都與媒體型別的解析有關,其中ContentTypeProvider屬性返回一個根據請求相對地址進行媒體型別的ContentTypeProvider物件。如果這個ContentTypeProvider不能正確解析出目標檔案的媒體型別,我們可以利用DefaultContentType設定一個預設媒體型別。但是隻有將另一個名為ServeUnknownFileTypes的屬性設定為True的情況下,媒體型別不能正常識別的請求採用使用這個預設設定的媒體型別。

StaticFileOptions還具有一個OnPrepareResponse屬性,它返回一個Action<StaticFileResponseContext>型別的委託物件,我們可以為這屬性指定的委託物件來對最終的響應進行定製。至於作為委託輸入引數的是一個型別為StaticFileResponseContext的物件,我們利用它可以獲得當前的HTTP上下文和目標檔案。

針對StaticFileMiddleware這個中介軟體的註冊一般都是呼叫針對ApplicationBuilder的UseStaticFiles擴充套件方法來完成的。具體來說,一共具有三個UseStaticFiles方法過載供我們選擇,如下所示的程式碼片段展示了這三個擴充套件方法的實現。

   1: public static class StaticFileExtensions
   2: {
   3:     public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app)
   4:     {
   5:         return app.UseMiddleware<StaticFileMiddleware>();
   6:     }
   7:  
   8:     public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app,StaticFileOptions options)
   9:     {      
  10:         return app.UseMiddleware<StaticFileMiddleware>(Options.Create<StaticFileOptions>(options));
  11:     }
  12:  
  13:     public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, string requestPath)
  14:     {       
  15:         StaticFileOptions options = new StaticFileOptions
  16:         {
  17:             RequestPath = new PathString(requestPath)
  18:         };
  19:         return app.UseStaticFiles(options);
  20:     }
  21: }

二、ContentTypeProvider

StaticFileMiddleware針對物理檔案請求的處理並不僅僅限於完成檔案內容的響應,還需要針對檔案的格式解析出正確的媒體型別。對於客戶端來說,如果無法確定媒體型別,獲取的檔案就像是一步無法解碼的天書,毫無意義。StaticFileMiddleware利用指定的ContentTypeProvider來解析媒體型別,ContentTypeProvider是我們對實現了IContentTypeProvider介面的所有型別以及對應物件的統稱。如下面的程式碼片段所示,IContentTypeProvider介面定義了唯一的方法TryGetContentType根據當前請求的相對路徑來解析這個作為輸出引數的媒體型別。

   1: public interface IContentTypeProvider
   2: {
   3:     bool TryGetContentType(string subpath, out string contentType);
   4: }

StaticFileMiddleware預設使用的ContentProvider是一個具有如下定義的FileExtensionContentTypeProvider物件。顧名思義,FileExtensionContentTypeProvider利用物理檔案的副檔名來解析對應的媒體型別,它利用其Mappings屬性表示的字典維護了一個副檔名與媒體型別之間的對映關係。我們常用的數百種標準的副檔名和對應的媒體型別之間的對映關係都會儲存在愛這個字典中。如果我們釋出的檔案具有一些特殊的副檔名,或者我們需要現有的某些副檔名對映為不同的媒體型別,這些通過新增或者修改對映關係來實現。

   1: public class FileExtensionContentTypeProvider : IContentTypeProvider
   2: {
   3:     public IDictionary<string, string> Mappings { get; }
   4:  
   5:     public FileExtensionContentTypeProvider();
   6:     public FileExtensionContentTypeProvider(IDictionary<string, string> mapping);
   7:  
   8:     public bool TryGetContentType(string subpath, out string contentType);
   9: }

三、利用配置指定StaticFileOptions

由於StaticFileMiddleware的建構函式用來設定相關選項的options引數型別為IOptions<StaticFileOptions>,所以我們可以根據Options模式將StaticFileOptions物件承載的部分選項定義在配置檔案中。比如我們利用如下所示的一個JSON檔案開啟了針對未知檔案型別的支援,並設定了預設使用媒體型別(“application/octet-stream”),這兩個配置項對應著StaticFileOptions的同名屬性。

   1: {
   2:   "serveUnknownFileTypes"    : true,
   3:   "defaultContentType"       : "application/octet-stream"
   4: }

有了這個配置檔案(假設檔名為“StaticFileOptions.json”),我們就可以按照如下的方式載入它並生成對應的Configuration物件,然後採用Options模式特有的程式設計模式實現與StaticFileOptions型別的對映。這樣的配置將會自動應用到註冊的StaticFileMiddleware中介軟體上。

   1: public class Program
   2: {
   3:     public static void Main()
   4:     {
   5:         IConfiguration config = new ConfigurationBuilder()
   6:             .AddJsonFile("StaticFileOptions.json")
   7:             .Build();
   8:  
   9:         new WebHostBuilder()
  10:             .UseContentRoot(Directory.GetCurrentDirectory())
  11:             .UseKestrel()
  12:             .ConfigureServices(svsc=>svsc.Configure<StaticFileOptions>(config))
  13:             .Configure(app=>app.UseStaticFiles())
  14:             .Build()
  15:             .Run();
  16:     }
  17: }

對於上面這樣的應用,所有未知檔案型別都將自動對映為“application/octet-stream”媒體型別。如果使用瀏覽器請求一個未知型別的檔案(比如前面演示的“~/wwwroot/img/ dophin1.img”),目標檔案將以如下圖所示的形式以一個附件的形式被下載。

7

四、實現原理

為了上讀者朋友們對針對靜態檔案的請求在StaticFileMiddleware中介軟體的處理具有更加深刻的認識,接下來我們會採用相對簡單的程式碼來重新定義這個中介軟體。這部分作為選修內容供有興趣的讀者朋友閱讀,忽略這些內容不會影響對後續內容的理解。這個模擬中介軟體具有與StaticFileMiddleware相同的能力,它能夠將目標檔案的內容採用正確的媒體型別響應給客戶端,同時能夠處理條件請求和區間請求。

8

StaticFileMiddleware中間處理針對靜態檔案請求的整個處理流程大體上可以劃分為如上圖所示的三個步驟:

  • 獲取目標檔案:中介軟體根據請求的路徑獲取目標檔案,並解析出正確的媒體型別。在此之前,中介軟體還會驗證請求採用的方法,它支援GETHEAD請求。除此之外,中介軟體還會獲取檔案最後被修改的時間,然後根據這個時間戳和檔案內容的長度生成一個簽名,響應訊息的Last-odified和ETag報頭的內容來源於此。
  • 條件請求解析:獲取與條件請求相關的四個報頭(If-Match、If-None-Match、If-Modified-Since和If-Unmodified-Since)的值,根據HTTP規範計算出最終的條件狀態。
  • 響應請求:如果是區間請求,中介軟體會獲取相關的報頭(Range和If-Range)解析出正確的內容區間。中介軟體最終根據上面計算的條件狀態和區間相關資訊設定響應的響應報頭,並根據需要響應整個檔案的內容或者指定區間的內容。

接下來我們按照上述的這個流程來重新定義這個StaticFileMiddleware,不過在此之前先來了解一下我們預先定義的幾個輔助性的擴充套件方法。如下面程式碼片段所示,擴充套件方法UseMethods用於判指定的請求是否採用指定的HTTP方法,而TryGetSubpath用於解析請求的目標檔案的相對路徑。TryGetContentType方法會根據指定的StaticFileOptions攜帶的ContentTypeProvider解析出正確的媒體型別,而TryGetFileInfo則根據指定的路徑獲取描述目標檔案的FileInfo物件。至於最後的IsRangeRequest方法,它會根據是否攜帶Rang報頭判斷指定的請求是否是一個區間請求。

   1: public static class Extensions
   2: {
   3:     public static bool UseMethods(this HttpContext context, params string[] methods)
   4:     {
   5:         return methods.Contains(context.Request.Method, StringComparer.OrdinalIgnoreCase);
   6:     }
   7:  
   8:     public static bool TryGetSubpath(this HttpContext context, string requestPath, out PathString subpath)
   9:     {
  10:         return new PathString(context.Request.Path).StartsWithSegments(requestPath, out subpath);
            
           

相關推薦

ASP.NET Core應用針對靜態檔案請求處理[3]: StaticFileMiddleware中介軟體如何處理針對檔案請求

我們通過《以Web的形式釋出靜態檔案》和《條件請求與區間請求》中的例項演示,以及上面針對條件請求和區間請求的介紹,從提供的功能和特性的角度對這個名為StaticFileMiddleware的中間進行了全面的介紹,接下來我們將更近一步,將從實現原理的角度來進一步認識這個中介軟體。 [本文已經同步到《ASP.NE

ASP.NET Core應用針對靜態檔案請求處理[2]: 條件請求與區間請求

通過呼叫ApplicationBuilder的擴充套件方法UseStaticFiles註冊的StaticFileMiddleware中介軟體幫助我們處理針對檔案的請求。對於StaticFileMiddleware處理請求的邏輯,大部分讀者都應該想得到:它根據請求的地址找到目標檔案的路徑,然後利用註冊的Cont

ASP.NET Core應用針對靜態檔案請求處理[1]: 以Web的形式釋出靜態檔案

雖然ASP.NET Core是一款“動態”的Web服務端框架,但是在很多情況下都需要處理針對靜態檔案的請求,最為常見的就是這對JavaScript指令碼檔案、CSS樣式檔案和圖片檔案的請求。針對不同格式的靜態檔案請求的處理,ASP.NET Core為我們提供了三個中介軟體,它們將是本系列文章論述的重點。不過在

ASP.NET Core應用針對靜態檔案請求處理[4]: DirectoryBrowserMiddleware中介軟體如何呈現目錄結構

和StaticFileMiddleware中介軟體一樣,DirectoryBrowserMiddleware中間本質上還是定義了一個請求地址與某個物理目錄之間的對映關係,而目標目錄體現為一個FileProvider物件。當這個中介軟體接收到匹配的請求後,會根據請求地址解析出對應目錄的相對路徑,並利用這個Fil

ASP.NET Core應用針對靜態檔案請求處理[5]: DefaultFilesMiddleware中介軟體如何顯示預設頁面

DefaultFilesMiddleware中介軟體的目的在於將目標目錄下的預設檔案作為響應內容。我們知道,如果直接請求的就是這個預設檔案,那麼前面介紹的StaticFileMiddleware中介軟體會將這個檔案響應給客戶端。如果我們能夠將針對目錄的請求重定向到這個預設檔案上,一切就迎刃而解了。實際上Def

15.ASP.NET Core 應用程式中的靜態檔案中介軟體

在這篇文章中,我將向大家介紹,如何使用中介軟體元件來處理靜態檔案。這篇文章中,我們討論下面幾個問題:在ASP.NET Core中,我們需要把靜態檔案存放在哪裡?在ASP.NET Core中 wwwroot資料夾是啥?怎樣在ASP.NET Core應用程式中,配置靜態檔案中介軟體?UseFileServer中介

ASP.NET Core應用的錯誤處理[4]:StatusCodePagesMiddleware中介軟體如何針對響應碼呈現錯誤頁面

StatusCodePagesMiddleware中介軟體與ExceptionHandlerMiddleware中介軟體比較類似,它們都是在後續請求處理過程中“出錯”的情況下利用一個錯誤處理器來完成最終的請求處理與響應的任務。它們之間的差異在於對“錯誤”的界定上,對於ExceptionHandlerMiddl

Jexus針對Asp.net core應用程式的六大不可替代的優勢

3,高效能:Jexus本身是一款與nginx效能相當的高效能Web伺服器,而Jexus與Asp.net core之間,是TCP轉發,不是反向代理之類的HTTP轉發,沒有Http協議解析和重組的效能消耗,因此,Jexus能更好的呈現Asp.net Core的高效能優勢;

ASP.NET Core WebAPI 開啟靜態網頁,設定主頁,跨域,Json保持原始大小寫,新增MIME,解除大檔案上傳限制

開啟靜態網頁 Startup.Configure: app.UseStaticFiles(); 設定主頁 Startup.Configure: DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions();

(5)ASP.NET Core 中的靜態檔案

1.前言 當我們建立Core專案的時候,Web根目錄下會有個wwwroot檔案目錄,wwwroot檔案目錄裡面預設有HTML、CSS、IMG、JavaScript等檔案,而這些檔案都是Core提供給客戶端使用的靜態檔案。但是這些靜態檔案需要在Core裡面配置才可以對外公開訪問。 2.設定靜態檔案目錄 靜

asp.net core 系列之靜態檔案

這篇講解asp.net core中的靜態檔案(大致翻譯於官網)。 靜態檔案,例如HTML,CSS, images和JavaScript. 要想直接被客戶端訪問,需要做一些配置。 一.Serve static files(提供靜態檔案服務) 靜態檔案儲存在專案的web root 目錄下。預設的目錄是<

Asp.Net Core入門之靜態檔案

靜態檔案(css,js,html等型別檔案)通常位於 web根目錄下,而ASP.Net Core框架預設內容根目錄下的wwwroot資料夾為web根目錄。這裡簡單解釋下內容根目錄:實際就是指包含可執行程式exe,程式集dll,配置檔案json,xml等的檔案目錄. 1.訪問web根目錄靜態檔案 正常

ASP.NET Core應用基本程式設計模式[1]:管道式的請求處理

HTTP協議自身的特性決定了任何一個Web應用的工作模式都是監聽、接收並處理HTTP請求,並且最終對請求予以響應。HTTP請求處理是管道式設計典型的應用場景:可以根據具體的需求構建一個管道,接收的HTTP請求像水一樣流入這個管道,組成這個管道的各個環節依次對其做相應的處理。雖然ASP.NET Core的請求處

Linux使用Jexus托管Asp.Net Core應用程序

技術 文件目錄 只需要 true 沒有 repr tag 博文 env 第一步 安裝.Net Core環境 安裝 dotnet 環境參見官方網站 https://www.microsoft.com/net/core。 選擇對應的系統版本進行安裝。安裝完成過後 輸入命令查

在 Azure WebApps 中運行64位 Asp.net Core 應用

需求 正常 mmu www. module .config 正在 external doc 作為微軟下一代的開源的跨平臺的開發框架, Asp.net core 正在吸引越來越多的開發者基於其構建現代 web 應用。 目前, Azure App Service 也實現了對 a

運行Vue在ASP.NET Core應用程序並部署在IIS上

生產環境 所在 來講 一個 重寫 文章 .net core 設置 分享 前言 從.NET Core 1.0開始我們就將其應用到項目中,但是呢我對ASP.NET Core一些原理也還未開始研究,僅限於會用,不過園子中已有大量文章存在,借著有點空余時間,我們來講講如何利用AS

ASP.NET Core應用程序部署至生產環境中(CentOS7)

for linux home web 虛擬 direct director block bic 閱讀目錄 環境說明 準備你的ASP.NET Core應用程序 安裝CentOS7 安裝.NET Core SDK for CentOS7。 部署ASP.NET

使用Docker部署ASP.NET Core應用程序實踐

4.0 cor run .com cnblogs pda word 本地配置 問題 前言 最近把很火的Docker給看了,於是就磨拳擦掌要去實踐一下。於是就拿之前一個aps.net core的項目(已被停止)去練手。該項目之前在ubuntu14.04上確保可以正常運行,所以

在 Docker 中部署 ASP.NET CORE 應用

post netcore 工作 ros core 指定 們的 本地 body 有了 Docker 之後, 部署起來卻這間非常方便,環境不用搭了, 直接創建一個 microsoft/aspnetcore 的容器, 在本地開發好後, 把內容直接部署到容器中。 下面的命令是把本

Docker打包 Asp.Net Core應用,在CentOS上運行(轉)

ner 表示 exec 但是 服務端 名稱 pro 目前 app 轉載連接:https://www.cnblogs.com/ibeisha/archive/2017/09/09/netcoreondocker.html 本文主要介紹下運用docker虛擬技術打包Asp.n