1. 程式人生 > >ASP.NET Core 2.2 基礎知識(三) 靜態檔案

ASP.NET Core 2.2 基礎知識(三) 靜態檔案

原文: ASP.NET Core 2.2 基礎知識(三) 靜態檔案

什麼是靜態檔案?

HTML,CSS,JS,圖片等都叫做靜態檔案.

要想提供靜態檔案給客戶端,需要註冊靜態檔案中介軟體.

我們先分別新增一個 WebAPI 專案,一個 Razor 檢視專案,比較兩個專案的 Startup 類的 Configure 方法: 

WebAPI專案:

 

Razor專案:

 

可以看出,Razor專案多了一行程式碼 app.UseStaticFiles();  (下面那一行先不管)

這行程式碼的作用就是註冊靜態檔案中介軟體.

UseStaticFiles() 方法的 xml 註釋是這樣寫的 : Enables static file serving for the current request path.為當前請求路徑提供靜態檔案服務.

之所以 WebAPI 專案沒有註冊靜態檔案中介軟體,是因為 WebAPI 的定義和 Razor,MVC 不一樣.

我們再來比較一下 WebAPI 專案和 Razor 專案:

(Pages 資料夾先不管)

可以看出,Razor 專案多了一個叫 wwwroot 的東西.別看它圖示是個球,其實它就是一個資料夾:

那麼問題來了,既然 Razor 專案提供了靜態檔案中介軟體,那這個 wwwroot 資料夾裡面的檔案怎麼訪問呢?他們的路徑是什麼呢?

比如,我們現在要訪問 wwwroot/css/site.css 

 

當然,如果我們把 app.UseStaticFiles(); 註釋掉,就404了:

 

從上面的例子中,可以看出,我們訪問的是路徑是: https://localhost:44301/css/site.css ,而不是  https://localhost:44301/wwwroot/css/site.css

顯然,系統默認了 wwwroot 資料夾,那這個預設的路徑在哪裡可以看呢?

我們在 Pages 檔案下的 Index.cshtml 頁面中增加如下程式碼:(紅色標註)

上面那行表示給 env 變數注入一個 IHostingEnvironment 型別的例項.

頁面顯示如下:

 

現在問題又來了,如果想訪問 wwwroot 資料夾外的檔案,應該怎麼設定路徑呢?

我們先新增一個資料夾 images,放入兩張圖片:

在 Startup 類中加入如下程式碼(紅色標註): 

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...other codes
app.UseStaticFiles();
       //下面這個靜態檔案中介軟體的設定,只針對其設定的檔案路徑下的檔案生效,和上面預設的靜態檔案路徑 wwwroot 下的檔案訪問相互獨立. app.UseStaticFiles(
new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Images")),//設定檔案路徑(物理路徑) RequestPath = new PathString(@"/files"),//設定訪問路徑(虛擬路徑) OnPrepareResponse = context => { context.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");//設定快取 }, });        
...other codes }

設定快取的程式碼是順帶寫的,僅僅表示有這個功能,跟設定路徑沒有關係.

請求自定義檔案路徑:

 

請求 wwwroot 資料夾下的檔案:

 

可以看到,響應中沒有快取設定了,這證明了兩者相互獨立.

除了可以設定檔案路徑,訪問路徑,快取外, StaticFileOptions 類還有3個屬性:

1.ContentTypeProvider  內容提供器

它的功能,直接看程式碼就明白了.

            var fileProvider = new FileExtensionContentTypeProvider();
            fileProvider.Mappings.Remove(".jpg");//移除對 ".jpg" 檔案的響應
            fileProvider.Mappings[".laotie"] = "image/jpeg";//新增對 ".laotie" 檔案的響應析,響應格式為 "image/jpeg"

            //下面這個靜態檔案中介軟體的設定,只針對其設定的檔案路徑下的檔案生效,和上面預設的靜態檔案路徑 wwwroot 下的檔案訪問相互獨立.
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Images")),//設定檔案路徑(物理路徑)
                RequestPath = new PathString(@"/files"),//設定訪問路徑(虛擬路徑)
                OnPrepareResponse = context =>
                {
                    context.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");//設定快取
                },
                ContentTypeProvider = fileProvider,//設定檔案提供器
            });

我們再次請求 : https://localhost:44301/files/1.jpg

 

 請求 : https://localhost:44301/files/3.laotie

 

2.ServeUnknownFileTypes

3.DefaultContentType

這兩個屬性一起說.

ServeUnknownFileTypes 的 xml 註釋是這樣寫的 : If the file is not a recognized content-type should it be served?Default: false. 如果檔案不是被認可的型別,那麼它是否應該提供(給客戶端)?預設:不提供.

那麼哪些型別是認可的呢?太多了....截一小部分圖:(這都是些啥型別啊,好詭異.小弟表示沒見過)

如果 ServeUnknownFileTypes 設定為 true,則表示要提供(給客戶端),而且是採用 DefaultContentType 屬性設定的響應型別提供.

而 DefaultContentType 的 xml 註釋是這樣寫的 :  

//The default content type for a request if the ContentTypeProvider cannot determine one. 如果 ContentTypeProvider  屬性設定的提供器不能選擇出一個認可的型別,則採用該屬性設定的響應型別.

//None is provided by default, so the client must determine the format themselves.如果該屬性沒有提供響應型別(即該屬性沒有值,為null),則交給客戶端來格式化它們.

測試如下:

我們將 上述程式碼中的 fileProvider.Mappings[".laotie"] = "image/jpeg" 註釋掉,註釋後的完整程式碼如下:

            var fileProvider = new FileExtensionContentTypeProvider();
            fileProvider.Mappings.Remove(".jpg");//移除對 ".jpg" 檔案的解析
            //fileProvider.Mappings[".laotie"] = "image/jpeg";//新增對 ".laotie" 檔案的解析,解析方式為 "image/jpeg"

            //下面這個靜態檔案中介軟體的設定,只針對其設定的檔案路徑下的檔案生效,和上面預設的靜態檔案路徑 wwwroot 下的檔案訪問相互獨立.
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Images")),//設定檔案路徑(物理路徑)
                RequestPath = new PathString(@"/files"),//設定訪問路徑(虛擬路徑)
                OnPrepareResponse = context =>
                {
                    context.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");//設定快取
                },
                ContentTypeProvider = fileProvider,//設定檔案提供器
            });

 

 我們再次請求 https://localhost:44301/files/3.laotie , 結果 404,因為我們刪掉了對 ".老鐵" 檔案型別的認可,而 ServeUnknownFileTypes  預設值又為 false

 

當我們把 ServeUnknownFileTypes 屬性設定為 ture :

            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Images")),//設定檔案路徑(物理路徑)
                RequestPath = new PathString(@"/files"),//設定訪問路徑(虛擬路徑)
                OnPrepareResponse = context =>
                {
                    context.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");//設定快取
                },
                ContentTypeProvider = fileProvider,//設定檔案提供器
                ServeUnknownFileTypes = true,
            });

再次請求 https://localhost:44301/files/3.laotie ,則正常顯示出了內容(圖就不上了)

我以為:如果設定 DefaultContentType  = "text/plain" ,那麼 3.laotie 應該不能正常訪問,但實際上還是可以訪問.有點不明白.希望高手解答一下.

 

跟檔案訪問相關的中介軟體,除了上面提到的靜態檔案中介軟體外,還有兩個:

1.預設檔案中介軟體 app.UseDefaultFiles()

預設檔案中介軟體的預設檔案有4種:default.htm,default.html,index.htm,index.html

當然,我們也可以自定義.

下面的示例給出了預設中介軟體的相關功能.

            //提供預設檔案
            DefaultFilesOptions options = new DefaultFilesOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Default")),
            };
            options.DefaultFileNames.Add("mydefault.html");//新增自定義的預設檔案
            app.UseDefaultFiles(options);

            app.UseStaticFiles();

            //使用靜態檔案中介軟體 
            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Default"))
            });

有兩點要特別注意:

1)必須在 UseStaticFiles 前呼叫 UseDefaultFiles .UseDefaultFiles 實際上用於重寫 URL,不提供檔案,真正提供檔案的依然是 UseStaticFiles .

2)兩個中介軟體的路徑必須設定一樣.理由就是第一條.

 

2.目錄瀏覽中介軟體  app.UseDirectoryBrowser()

該中介軟體的啟用方式,設定方式和靜態檔案中介軟體類似.

由於涉及安全考慮,微軟預設沒有啟動該中介軟體.

            //啟用目錄瀏覽中介軟體
            app.UseDirectoryBrowser();
            app.UseDirectoryBrowser(new DirectoryBrowserOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Images")),
                RequestPath = new PathString(@"/files"),
            });

 

除了上述3種檔案相關的中介軟體外,系統提供了一個3合一的中介軟體:

            //同時啟用預設的靜態檔案,預設檔案,靜態目錄瀏覽中介軟體,false 則不啟動靜態目錄瀏覽.
            app.UseFileServer(true);

處於安全考慮,要啟動目錄瀏覽中介軟體,需要傳入 true .

 

完.