日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core应用针对静态文件请求的处理[1]: 以Web的形式发布静态文件

發布時間:2023/12/20 asp.net 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core应用针对静态文件请求的处理[1]: 以Web的形式发布静态文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

雖然ASP.NET Core是一款“動態”的Web服務端框架,但是在很多情況下都需要處理針對靜態文件的請求,最為常見的就是這對JavaScript腳本文件、CSS樣式文件和圖片文件的請求。針對不同格式的靜態文件請求的處理,ASP.NET Core為我們提供了三個中間件,它們將是本系列文章論述的重點。不過在針對對它們展開介紹之前,我們照理通過一些簡單的實例來體驗一下如何在一個ASP.NET Core應用中發布靜態文件。[本文已經同步到《ASP.NET Core框架揭秘》之中]

目錄
一、以Web的形式讀取文件
二、瀏覽目錄內容
三、顯示默認頁面
四、映射媒體類型

一、以Web的形式讀取文件

我們創建的演示實例是一個簡單的ASP.NET Core控制臺應用,它具有如下圖所示的項目結構。我們可以看到在默認作為WebRoot的目錄(wwwroot)下,我們將JavaScript腳本文件、CSS樣式文件和圖片文件存放到對應的子目錄(js、css和img)下,我們將把這個目錄的所有文件以Web的形式發布出來,客戶端可以訪問相應的URL來獲取這些文件。

針對靜態文件的請求是通過一個名為StaticFileMiddleware的中間件來實現的,這個中間件類型定義在NuGet包“Microsoft.AspNetCore.StaticFiles”中,所以我們需要預先按照這個NuGet包。整個應用只包含如下所示的這幾行代碼,StaticFileMiddleware這個中間件的注冊是通過調用ApplicationBuilder的擴展方法UseStaticFiles來完成的。

1: public class Program 2: { 3: public static void Main() 4: { 5: new WebHostBuilder() 6: .UseContentRoot(Directory.GetCurrentDirectory()) 7: .UseKestrel() 8: .Configure(app => ) 9: .Build() 10: .Run(); 11: } 12: }

除了注冊必需的StaticFileMiddleware中間件之外,我們還調用了WebHostBuilder的UseContentRoot方法將當前項目的根目錄作為ContentRoot目錄。我們知道ASP.NET Core應用具有兩個重要的根目錄,它們分別是ContentRoot和WebRoot,后者也是對外發布的靜態文件默認使用的根目錄。由于WebRoot目錄的默認路徑就是“{contentroot}/wwwroot”,所示上面這段程序就是將項目中的這個wwwroot目錄下的所有靜態文件發布出來。

當這個程序運行之后,我們就可以通過向對應URL發送HTTP請求的方式來獲取某個的文件,這個URL由文件相當于wwwroot目錄的路徑來決定。比如JPG文件“~/wwwroot/img/dophin1.jpg”對應的URL為“http://
localhost:5000/img/dophin1.jpg”。我們直接利用瀏覽器訪問這個URL,目標圖片會直接顯示出來。

上面我們通過一個簡單的實例將WebRoot所在目錄下的所有靜態文件直接發布出來。如果我們需要發布的靜態文件存儲在其他目錄下呢?依舊是演示的這個應用,現在我們將一些文檔存儲在如下圖所示的“~/doc/”目錄下并以Web的形式發布出來,我們的程序又該如何編寫呢?

我們知道ASP.NET Core應用大部分情況下都是利用一個FileProvider對象來讀取文件的,它在處理針對靜態文件的請求是也不例外。對于我們調用ApplicationBuilder的擴展方法UseStaticFiles方法注冊的這個類型為StaticFileMiddleware的中間件,其內部具有一個FileProvider和請求路徑的映射關系。如果調用UseStaticFiles方法沒有指定任何的參數,那么這個映射關系的請求路徑就是應用的基地址(PathBase),而FileProvider自然就是指向WebRoot目錄的PhysicalFileProvider。

上述的這個需求可以通過顯式注冊這個映射的方式來實現,為此我們在現有程序的基礎上額外添加了一次針對UseStaticFiles方法的調用,并通過指定的參數(是一個StaticFileOptions對象)顯式指定了采用的FileProvider(針對“~/doc/”的PhysicalFileProvider)和請求路徑(“/documents”)。

1: public class Program 2: { 3: public static void Main() 4: { 5: string contentRoot = Directory.GetCurrentDirectory(); 6: new WebHostBuilder() 7: .UseContentRoot(contentRoot) 8: .UseKestrel() 9: .Configure(app => app 10: .UseStaticFiles() 11: .UseStaticFiles(new StaticFileOptions { 12: FileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc")), 13: RequestPath = "/documents" 14: })) 15: .Build() 16: .Run(); 17: } 18: }

按照上面這段程序指定的映射關系,對于存儲在“~/doc/”目錄下的這個PDF文件(“checklist.pdf”),發布在Web上的URL為“http://localhost:5000/documents/checklist.pdf”。當我們在瀏覽器上請求這個地址時,該PDF文件的內容將會按照如下圖所示的形式顯示在瀏覽器上。

二、瀏覽目錄內容

注冊的StaticFileMiddleware中間件只會處理針對某個具體靜態文件的額請求,如果我們向針對某個目錄的URL發送HTTP請求(比如“http://localhost:5000/img/”),得到的將是一個狀態為404的響應。不過我們可以通過注冊另一個名為DirectoryBrowserMiddleware的中間件來顯示請求目錄的內容。具體來說,這個中間件會返回一個HTML頁面,請求目錄下的所有文件將以表格的形式包含在這個頁面中。對于我們演示的這個應用來說,我們可以按照如下的方式調用UseDirectoryBrowser方法來注冊這個DirectoryBrowserMiddleware中間件。

1: public class Program 2: { 3: public static void Main() 4: { 5: string contentRoot = Directory.GetCurrentDirectory(); 6: IFileProvider fileProvider = new PhysicalFileProvider( 7: Path.Combine(contentRoot, "doc")); 8: new WebHostBuilder() 9: .UseContentRoot(contentRoot) 10: .UseKestrel() 11: .Configure(app => app 12: .UseStaticFiles() 13: .UseStaticFiles(new StaticFileOptions { 14: FileProvider = fileProvider, 15: RequestPath = "/documents" 16: }) 17: . 18: . 19: 20: 21: })) 22: .Build() 23: .Run(); 24: } 25: }

當上面這個應用啟動之后,如果我們利用瀏覽器向針對某個目錄的URL(比如“http://localhost:5000/”或者“http://localhost:5000/img/”),目標目錄的內容(包括子目錄和文件)將會以下圖所示的形式顯示在一個表格中。不僅僅如此,子目錄和文件均會顯示為鏈接,指向目標目錄或者文件的URL。

三、顯示默認頁面

從安全的角度來講,利用注冊的UseDirectoryBrowser中間件顯示一個目錄瀏覽頁面會將整個目標目錄的接口和所有文件全部暴露出來,所以這個中間件需要根據自身的安全策略謹慎使用。對于針對目錄的請求,另一種更為常用的響應策略就是顯示一個保存在這個目錄下的默認頁面。按照約定,作為默認頁面的文件一般采用如下四種命名方式:default.htm、default.html、index.htm或者index.html。針對目標目錄下默認頁面的呈現實現在一個名為DefaultFilesMiddleware的中間件中,我們演示的這個應用可以按照如下的方式調用UseDefaultFiles方法來注冊這個中間件。

1: public class Program 2: { 3: public static void Main() 4: { 5: string contentRoot = Directory.GetCurrentDirectory(); 6: IFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc")); 7:? 8: new WebHostBuilder() 9: .UseContentRoot(contentRoot) 10: .UseKestrel() 11: .Configure(app => app 12: 13: 14: 15: 16: 17: .UseStaticFiles() 18: .UseStaticFiles(new StaticFileOptions 19: { 20: FileProvider = fileProvider, 21: RequestPath = "/documents" 22: }) 23: .UseDirectoryBrowser() 24: .UseDirectoryBrowser(new DirectoryBrowserOptions 25: { 26: FileProvider = fileProvider, 27: RequestPath = "/documents" 28: })) 29: .Build() 30: .Run(); 31: } 32: }

現在我們在“~/wwwroot/img/”目錄下創建一個名為index.htm的默認頁面,現在利用瀏覽器訪問這個目錄對應的URL(“http://localhost:5000/img/”),顯示就時這個頁面的內容。

我們必須在注冊StaticFileMiddleware和DirectoryBrowserMiddleware之前注冊DefaultFilesMiddleware,否則它起不了任何作用。由于DirectoryBrowserMiddleware和DefaultFilesMiddleware這兩個中間件處理的均是針對目錄的請求,如果DirectoryBrowserMiddleware先被注冊,那么顯示的總是目錄的內容。若DefaultFilesMiddleware先被注冊,在默認頁面不存在情況下回顯示目錄的內容。至于為什么要先于StaticFileMiddleware之前注冊DefaultFilesMiddleware,則是因為后者是通過采用URL重寫的方式實現的,也就是說這個中間件會將針對目錄的請求改寫成針對默認頁面的請求,而最終針對默認頁面的請求還得依賴StaticFileMiddleware完成。

DefaultFilesMiddleware中間件在默認情況下總是以約定的名稱(default.htm、default.html、index.htm或者index.html)在當前請求的目錄下定位默認頁面。如果我們希望作為默認頁面的文件不能按照這樣的約定命名(比如readme.htm),我們需要按照如下的方式顯式指定默認頁面的文件名。

1: public class Program 2: { 3: public static void Main() 4: { 5: string contentRoot = Directory.GetCurrentDirectory(); 6: IFileProvider fileProvider = new PhysicalFileProvider(Path.Combine(contentRoot, "doc")); 7:? 8: DefaultFilesOptions options1 = new DefaultFilesOptions(); 9: DefaultFilesOptions options2 = new DefaultFilesOptions{ 10: RequestPath = "/documents", 11: FileProvider = fileProvider 12: }; 13: options1.DefaultFileNames.Add("readme.htm"); 14: options2.DefaultFileNames.Add("readme.htm"); 15:? 16: new WebHostBuilder() 17: .UseContentRoot(contentRoot) 18: .UseKestrel() 19: .Configure(app => app 20: .UseDefaultFiles(options1) 21: .UseDefaultFiles(options2) 22: .UseStaticFiles() 23: .UseStaticFiles(new StaticFileOptions{ 24: FileProvider = fileProvider, 25: RequestPath = "/documents" 26: }) 27: .UseDirectoryBrowser() 28: .UseDirectoryBrowser(new DirectoryBrowserOptions{ 29: FileProvider = fileProvider, 30: RequestPath = "/documents" 31: })) 32: .Build() 33: .Run(); 34: } 35: }

四、映射媒體類型

通過上面演示的實例可以看出,瀏覽器能夠正確的將請求的目標文件的內容正常的呈現出來。對HTTP協議具有基本了解的人都應該知道,響應的文件能夠在支持的瀏覽器上呈現具有一個基本的前提,那就是響應消息通過Content-Type報頭攜帶的媒體類型必須與內容一致。我們的實例演示了針對兩種類型文件的請求,一種是JPG文件,另一種是PDF文件,對應的媒體類型分別是“image/jpg”和“application/pdf”,那么StaticFileMiddleware是如何正確解析出正確的媒體類型的呢?

StaticFileMiddleware針對媒體類型的解析是通過一個名為ContentTypeProvider的對象來實現的,而默認使用的則是一個FileExtensionContentTypeProvider對象。顧名思義,FileExtensionContentTypeProvider是根據文件的擴展命名來解析媒體類型的。FileExtensionContentTypeProvider內部預定了數百種常用文件擴展名與對應媒體類型之間的映射關系,所以如果我們發布的靜態文件具有標準的擴展名,StaticFileMiddleware就能為對應的響應賦予正確的媒體類型。

那么如果某個文件的擴展名沒有在這個預定義的映射之中,或者我們需要某個預定義的擴展名匹配不同的媒體類型,我們應該如何解決呢?還是針對我們演示的這個實例,想在我將“~/wwwroot/img/ dophin1.jpg”這個文件的擴展名改成“.img”,毫無疑問StaticFileMiddleware將能為針對該文件的請求解析出正確媒體類型。這個問題具有若干不同的解決方案,第一種方案就是讓StaticFileMiddleware支持不能識別的文件類型,并為它們設置一個默認的媒體類型,如下所示了具體采用的編程方式。

1: public class Program 2: { 3: public static void Main() 4: { 5: new WebHostBuilder() 6: .UseContentRoot(Directory.GetCurrentDirectory();) 7: .UseKestrel() 8: .Configure(app => app.UseStaticFiles(new StaticFileOptions { 9: 10: 11: })) 12: .Build() 13: .Run(); 14: } 15: }

上述這種解決方案只能設置一種默認媒體類型,如果具有多種需要映射成不同媒體類型的非識別文件類型,采用這種方案就無能為力了,所以最根本的解決方案還是需要將不能識別的文件類型和對應的媒體類型進行映射。由于StaticFileMiddleware使用的ContentTypeProvider是可以定制的,我們可以按照如下的方式顯式地為StaticFileMiddleware指定一個FileExtensionContentTypeProvider對象作為它的ContentTypeProvider,然后將取缺失的映射添加到這個FileExtensionContentTypeProvider對象上。

1: public class Program 2: { 3: public static void Main() 4: { 5: FileExtensionContentTypeProvider contentTypeProvider = new FileExtensionContentTypeProvider(); 6: 7:? 8: new WebHostBuilder() 9: .UseContentRoot(Directory.GetCurrentDirectory()) 10: .UseKestrel() 11: .Configure(app => app.UseStaticFiles(new StaticFileOptions{ 12: ContentTypeProvider = contentTypeProvider 13: })) 14: .Build() 15: .Run(); 16: } 17: }

?


ASP.NET Core應用針對靜態文件請求的處理[1]: 以Web的形式發布靜態文件
ASP.NET Core應用針對靜態文件請求的處理[2]: 條件請求與區間請求
ASP.NET Core應用針對靜態文件請求的處理[3]: StaticFileMiddleware中間件如何處理針對文件請求
ASP.NET Core應用針對靜態文件請求的處理[4]: DirectoryBrowserMiddleware中間件如何呈現目錄結構
ASP.NET Core應用針對靜態文件請求的處理[5]: DefaultFilesMiddleware中間件如何顯示默認頁面

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。 原文鏈接

總結

以上是生活随笔為你收集整理的ASP.NET Core应用针对静态文件请求的处理[1]: 以Web的形式发布静态文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。