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 .

 

完.

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM