歡迎光臨
每天分享高質量文章

ASP.NET Core 檔案系統

緊接上一講 中介軟體 之後,今天來我們來講一下關於 ASP.NET  Core 中靜態檔案服務。


什麼是靜態檔案?

先看一下下麵例子(在客戶端瀏覽器中透過 url 路徑訪問了網站的一張圖片):

這樣的圖片就是一個靜態檔案

  • 靜態檔案(staticfiles),其實就是指像 HTMLCSS圖片 和 JavaScript 之類固定的檔案,是會被應用程式直接提供給客戶端的資源。

  • 靜態檔案通常位於web root(內容根目錄或Web根目錄)檔案夾下。有關 內容根目錄 和 Web根目錄 的資訊在第一講中介紹過。

    •  Web根目錄預設為的是 Contentroot 路徑下的 wwwroot 檔案夾。
    •  靜態檔案中介軟體將預設只讀取 Web根目錄和其子目錄中的檔案。
    •  對於 Razor (.cshtml) 檔案,波浪號斜槓 ~/ 指向 webroot。 以 ~/ 開頭的路徑稱為虛擬路徑。
    • 內容根目錄(Contentroot):是應用程式所用到的所有內容的根路徑。WebHost.CreateDefaultBuilder() 中預設下把專案的當前目錄設定為內容根目錄,也就是指 web 的專案的檔案夾,包括 bin 和 webroot 檔案夾。
    • Web根目錄(webroot):專案中用於存放類似於 CSS、JS、圖片等公開、靜態資源的目錄。
  • 靜態檔案可以儲存在 Web根目錄(預設為wwwroot) 下的任意檔案夾內,並透過相對根的路徑來訪問。例如當你透過 VisualStudio 建立一個預設的 Web應用程式(MVC)專案時,在 wwwroot 目錄下會多出幾個檔案夾:css、images以及js。

    透過下麵的URL就能夠直接訪問 images 目錄下的圖片:
    http:///images/
    http://localhost:7819/images/banner1.svg


靜態檔案中介軟體

如上例子,為了能夠使用靜態檔案的服務,必須配置中介軟體,把靜態檔案中介軟體加入到請求管道內。(預設建立的 MVC Web應用程式已經配置了)
靜態檔案中介軟體可透過下述方法來配置:在專案中增加 MicrosoftAspNetCore.StaticFiles 包依賴,然後從Startup.Configure 中呼叫 app.UseStaticFiles 擴充套件方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){
    app.UseStaticFiles();
} 

上面我們透過一個簡單的實體使用 app.UseStaticFiles() 來使用檔案中介軟體,使得Web根目錄下的所有靜態檔案直接釋出出來。如果我們需要釋出的靜態檔案儲存在其他目錄下呢?依舊是這個應用,現在我們將靜態檔案放在自定義檔案夾 MyStaticFiles 內,並將以Web的形式釋出出來,展示如何透過使用 UseStaticFiles將其他非wwwroot目錄下的內容也向外提供服務。

7Vtdk5owFP01PnaHEEB9rPbroZ3pdDvT5ygR00ZCQyxuf31vIBHZ6K6tQN1ddpydcMNHcs89h9wbHeH5Zvdekmz9ScSUj3wv3o3wm5HvY8+D/9pwVxkCNK4MiWRxZfJqwy37TSsjstYti2neOFEJwRXLjBFVxqVIU7pUjROJlKJoXrsSPG5cl5GEOobbJeGu9RuL1bqyTvxxbf9AWbI2T0YomlY9C7L8kUixTc3zRj5elX9V94bYe5mR5WsSi+LAhN+O8FwKoarWZjenXLu26bZ3J3r345Y0Vedc4FcX/CJ8S+2Iy3GpO+sLGGKmm3BTxQj/Av4maaJ7Z0pk0OFBi9OVMk1p/KLbC6GU2JgDwlmSQrs6d/aLwv3A5a+NubzZbMU4nwsuJFhSkeqn5BlZsjT5WD0i8mrTF/OoAEwC7rfipS/XLI5pqociFFFkUc5EX5YJlqoyNMIZfMA1c+8mHIUwzTkco/oYPvp0qeYizZUkrHQnJbkqaK5HH0uRfSUyoXaqK5EqE8gIYJy5SBhw9Lzp7sBkkHlPxYYqeQenmN7QBIkl0WRSHRd1SCIbSOuDcPQjwwTDgmR/5zoSoGGC4Xhg4IsCo3SGOROdCpRGcBzB/ax4aQZH0FZsPAa/nrOZ2+PA+yeA3+uXGUZDAxoBcYB4GHUDePA44JxVfFRS/NjrIvon8DYAAz8g99cyQF4hB1HsIoqPoMfJgvLPImeKCX1/I0J/iWoHHEZe1CRxhBwSW98fQjq5HNFw0PYno+0hwv1pezRoe2vaHp4A/qq0fTwowZNRAjzpUQkmgxK0pgTjE8BflRJMByV4MkoQeNP+lMBWXgYpaEEKpieQvyopQMhBvCiKsvTkR1zPeSGhlaj9FA9CAeal7Wu14cYrVVZ4D9EHQF6Ct6h8KDUs1kzRWwBXP7OQJCtB3KYxjQ2ELXAO4Xv5WRg6pAuOcc5rAQE354bwUzCZl4aCrWzZNVDk9QfCGWnyUPhoofBxZF3bUeEDuQnup7tb8BtbvmOc5s+XRyiYNp0+HvdHpDOSiYFIf4+p743vESnojUhuuqBgnjdZmjxfDvk4/G8c8s9YhQ8cuvxlhKd+Xxzy3WX2gqXPlz7Ihuy+ntXfgto+eqBPx2s5u8LqgT7uRrRYfH859Ak8d9O/M/q4qdBnKTLtj+e9aEZNl2N3i7Yzl1+2FzcUZHstyGL3VdZZQfbCTbuhINv4Bk50AvqrqsheuB03iEGvYnCkRtmdGFy2bzeIQUMMJiegvyoxwG7e6EA+5DIt5DLYXWB3lMvgY+mp2eRpABv93Ao7/Vd5Of/XcAIKsl3daXeFbtyNoodMMMhFvaH0craYEGqWxkOLRg+rfHzGt6kHLl/O5dDrrS6B3b1bBgG7uymZcs0sOvLac0B4IFe+twqaut9RaYlFcFj/DqbsO/itEX77Bw==

如果要訪問 MyStaticFiles 檔案夾下的 test.png 圖片,可以這樣配置靜態檔案中介軟體:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){
    app.UseStaticFiles();
    app.UseStaticFiles(new StaticFileOptions() 
    {
  FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")), 
        RequestPath = new PathString("/StaticFiles"), 
    });
}

ASP.NET Core 一般情況下都是利用一個FileProvider 物件來讀取檔案的,它在處理針對靜態檔案的請求是也不例外。

上邊程式碼在靜態檔案中介軟體中,在呼叫靜態檔案中介軟體的方法 UseStaticFiles(),該方法可接受一個配置項物件 StaticFileOptions,其內部具有一個 FileProvider 和請求路徑的對映關係。

如果呼叫 UseStaticFiles方法沒有指定任何的引數,那麼這個對映關係的請求路徑就是應用的基地址(PathBase),而FileProvider自然就是指向WebRoot目錄的PhysicalFileProvider。

透過訪問 http:///StaticFiles/test.png,這樣就能訪問到 test.png 圖片檔案了。

靜態檔案授權 :

靜態檔案中介軟體預設不提供授權檢查。任何透過該模組提供訪問的檔案,包括位丁 wwwroot 下的檔案都是公開的,那麼如何給檔案提供授權呢?

將檔案儲存在 wwwroot 之外,並將目錄設定為可被靜態檔案中介軟體訪問到,同時透過一個 controller action 來訪問,透過授權後傳回HleResulU將檔案儲存在wwwroot之外,並將目錄設定為可被靜態檔案中介軟體訪問到,同時透過一個itrolleraction來訪問,透過授權後傳回 FileResult。


目錄瀏覽

以上透過註冊的 StaticFileMiddleware 只會處理針對某個具體靜態檔案的請求,如果我們向某個目錄的URL傳送HTTP請求,得到的將是一個狀態為404的響應。那是因為基於安全考慮,預設情況下應用程式是禁用目錄訪問功能的。目錄瀏覽就是允許網站使用者看到指定目錄下的目錄和檔案串列。我們可以透過註冊一個名為DirectoryBrowserMiddleware 的中介軟體來顯示請求目錄的內容:

Step1. 在Startup.ConfigureServices 中呼叫 AddDirectoryBrowser 擴充套件方法新增目錄瀏覽服務:

public void ConfigureServices(IServiceCollection services){
    services.AddDirectoryBrowser();
}

Step2. 然後在 Startup.Configure 中呼叫 UseDirectoryBrowser 擴充套件方法使用中介軟體來開啟網路應用目錄瀏覽:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){
    app.UseStaticFiles();
    
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
    });
    
    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
    });
}

執行程式後,就可以透過訪問 http:/StaticFiles 來瀏覽 ContentRoot/StaticFiles 檔案夾中的目錄了。這個中介軟體會傳回一個HTML頁面,將請求目錄下的所有檔案將以表格的形式包含在這個頁面中(包括該檔案夾下的每一個檔案夾與檔案)

註意:使用靜態檔案目錄瀏覽的區別,上述Step2.Startup.Configure方法中呼叫了兩個 app.UseStaticFiles:第一個呼叫允許請求 wwwroot 檔案夾下的靜態檔案,第二個呼叫則是允許透過 http:/StaticFiles/ 請求 StaticFiles 檔案夾中的靜態檔案,呼叫 app.UseDirectoryBrowser 則是允許透過 http:/StaticFiles 請求瀏覽 StaticFiles 檔案夾的目錄。

註冊指定目錄的瀏覽

   app.UseDirectoryBrowser 方法可接受一個配置項物件 DirectoryBrowserOptions,該物件與靜態檔案中介軟體配置項物件相似,透過該物件可以配置允許使用者瀏覽的目錄和請求的虛擬路徑。


預設檔案

設定預設首頁能給站點的每個訪問者提供一個預設起始頁。為了使站點能夠提供預設頁面,避免使用者輸入完整URL,我們可以在 Startup.Configure 中呼叫 app.UseDefaultFiles 擴充套件方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){
    app.UseDefaultFiles();
    app.UseStaticFiles();
}

app.UseDefaultFiles 必須是在 UseStaticFiles 之前呼叫。UseDefaultFiles只是重寫了URL,而不是真的提供了這樣一個檔案。因此必須開啟靜態檔案中介軟體(UseStaticFiles)來提供這個檔案。
透過 UseDefanltFiles,請求檔案夾的時候將檢索以下檔案:

  • default.htm
  • default.html
  • index.htm
  • index.html

串列中第一個被找到的檔案將傳回給使用者,作為該完整URL的請求的應答,而此時瀏覽器上URL將繼續顯示使用者輸入的URI。

指定預設檔案

靜態檔案中介軟體可以接受一個 DefaultFilesOptions 的配置物件引數,透過新增預設主頁名稱,可以指定自定義的預設檔案(預設首頁),下麵的程式碼展示如何將預設檔案名改為 myindex.html

public void Configure(IApplicationBuilder app)
{
	DefaultFilesOptions options = new DefaultFilesOptions();
	options.DefaultFileNames.Clear(); // 清除預設檔案
	options.DefaultFileNames.Add("login.html"); //新增指定檔案為預設檔案
	app.UseDefaultFiles(options); //使用預設檔案中介軟體
	app.UseStaticFiles();     //使用靜態檔案中介軟體(必須)
}

在 web根目錄中新增好 login.html 頁面,執行程式:


UseFileServer

UseFileServer 集合了 UseStaticFilesUseDefaultFiles以及UseDirectoryBrowser
下麵的程式碼啟用了靜態檔案和預設檔案,但不允許直接訪問目錄:

下麵的程式碼啟用了靜態檔案、預設檔案和目錄瀏覽功能:

app.UseFileServer(enableDirectoryBrowsing:true);

作為一個集合了UseStaticFilesUseDefaultFilesUseDirectoryBrowser方法於一體的方法,如果希望提供 web根目錄之外存在的檔案,則需要實體化並配置一個 FileServerOptions 物件傳遞給app.UscFileServer 的引數。例如,在應用中有如下層次的目錄:

7Vtdk5owFP01PnaHEEB9rPbroZ3pdDvT5ygR00ZCQyxuf31vIBHZ6K6tQN1ddpydcMNHcs89h9wbHeH5Zvdekmz9ScSUj3wv3o3wm5HvY8+D/9pwVxkCNK4MiWRxZfJqwy37TSsjstYti2neOFEJwRXLjBFVxqVIU7pUjROJlKJoXrsSPG5cl5GEOobbJeGu9RuL1bqyTvxxbf9AWbI2T0YomlY9C7L8kUixTc3zRj5elX9V94bYe5mR5WsSi+LAhN+O8FwKoarWZjenXLu26bZ3J3r345Y0Vedc4FcX/CJ8S+2Iy3GpO+sLGGKmm3BTxQj/Av4maaJ7Z0pk0OFBi9OVMk1p/KLbC6GU2JgDwlmSQrs6d/aLwv3A5a+NubzZbMU4nwsuJFhSkeqn5BlZsjT5WD0i8mrTF/OoAEwC7rfipS/XLI5pqociFFFkUc5EX5YJlqoyNMIZfMA1c+8mHIUwzTkco/oYPvp0qeYizZUkrHQnJbkqaK5HH0uRfSUyoXaqK5EqE8gIYJy5SBhw9Lzp7sBkkHlPxYYqeQenmN7QBIkl0WRSHRd1SCIbSOuDcPQjwwTDgmR/5zoSoGGC4Xhg4IsCo3SGOROdCpRGcBzB/ax4aQZH0FZsPAa/nrOZ2+PA+yeA3+uXGUZDAxoBcYB4GHUDePA44JxVfFRS/NjrIvon8DYAAz8g99cyQF4hB1HsIoqPoMfJgvLPImeKCX1/I0J/iWoHHEZe1CRxhBwSW98fQjq5HNFw0PYno+0hwv1pezRoe2vaHp4A/qq0fTwowZNRAjzpUQkmgxK0pgTjE8BflRJMByV4MkoQeNP+lMBWXgYpaEEKpieQvyopQMhBvCiKsvTkR1zPeSGhlaj9FA9CAeal7Wu14cYrVVZ4D9EHQF6Ct6h8KDUs1kzRWwBXP7OQJCtB3KYxjQ2ELXAO4Xv5WRg6pAuOcc5rAQE354bwUzCZl4aCrWzZNVDk9QfCGWnyUPhoofBxZF3bUeEDuQnup7tb8BtbvmOc5s+XRyiYNp0+HvdHpDOSiYFIf4+p743vESnojUhuuqBgnjdZmjxfDvk4/G8c8s9YhQ8cuvxlhKd+Xxzy3WX2gqXPlz7Ihuy+ntXfgto+eqBPx2s5u8LqgT7uRrRYfH859Ak8d9O/M/q4qdBnKTLtj+e9aEZNl2N3i7Yzl1+2FzcUZHstyGL3VdZZQfbCTbuhINv4Bk50AvqrqsheuB03iEGvYnCkRtmdGFy2bzeIQUMMJiegvyoxwG7e6EA+5DIt5DLYXWB3lMvgY+mp2eRpABv93Ao7/Vd5Of/XcAIKsl3daXeFbtyNoodMMMhFvaH0craYEGqWxkOLRg+rfHzGt6kHLl/O5dDrrS6B3b1bBgG7uymZcs0sOvLac0B4IFe+twqaut9RaYlFcFj/DqbsO/itEX77Bw==

對於上面這個層次結構的示例,你可能需耍啟用靜態檔案、預設檔案以及瀏覽 MyStaticFiles 目錄等功能。下麵的程式碼片段演示瞭如何透過呼叫一次 FileServerOptions 來完整實現這些功能:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){
    app.UseFileServer(new FileServerOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
        EnableDirectoryBrowsing = true,
        EnableDefaultFiles = true,
    });
}

如果將 enableDirectoryBrowsing設定為true,則必須要在 Startup.ConfigureServices 中呼叫 services.AddDirectoryBrowser 擴充套件方法:

public void ConfigureServices(IServiceCollection services){
    services.AddDirectoryBrowser();
}

如果在 MyStaticFiles 目錄下存在預設頁面,則開啟預設頁面。如果沒有預設命名的檔案,則http://StaticFiles將傳回目錄 StaticFiles 的目錄串列,如下圖所示。

StaticFiles中存在預設頁面

StaticFiles中不存在預設頁面


FileExtensionContentTypeProvider

FileExtensionContentTypeProvider 類內包含一個將檔案副檔名對映到 MIME內容型別的集合。在下麵的例子中,將多個檔案副檔名(如:.myapp)註冊為已知的MIME型別(application/x-msdownload),“.rtf”被替換,“.mp4”被移除:

public void Configure(IApplicationBuilder app){
    FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
    
    provider.Mappings[".myapp"] = "application/x-msdownload";
    provider.Mappings[".htm3"] = "text/html";
    provider.Mappings[".image"] = "image/png";

    
    provider.Mappings[".rtf"] = "application/x-msdownload";

    
    provider.Mappings.Remove(".mp4");
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
        ContentTypeProvider = provider,
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
    });
}

非標準的內容型別

ASP.NET Core 靜態檔案中介軟體能夠支援超過400多種己知的檔案內容型別。如果使用者請求一個未知的檔案型別,靜態檔案中介軟體將返 HTTP404(未找到)響應。如果啟用目錄瀏覽,則該檔案的URL將會被顯示,但訪問URL會傳回一個 HTTP404 錯誤。下麵則透過程式碼把不能識別的型別和檔案作為下載的檔案處理:

public void Configure(IApplicationBuilder app){
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
        ServeUnknownFileTypes = true,
        DefaultContentType = "application/x-msdownload",
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")),
        RequestPath = new PathString("/StaticFiles"),
    });

}

註意事項:

  • UseDirectoryBrowser 和 UseStaticFiles 可能會洩密。建議不要在生產環境開啟目錄瀏覽。要小心那些被你開啟了 UseStaticFiles 或 UseDirectoryBrowser 的目錄,它們的子檔案及子目錄都可被訪問。建議將公開內容放在/wwwroot 這樣的目錄中,遠離應用程檢視、配置檔案等。
  • 使用 UseDirectoryBrowser 和 UseStaticFiles 暴露的檔案的 URL是否區分大小寫以及字元限制,受制於底層檔案系統。比如Windows是不區分大小寫的,但MACOS和Linux則區分大小寫。

實戰簡單檔案伺服器

① 首先新建一個ASP.NETCore專案,選擇空的模板。
② 使用NuGet命令新增Microsoft.AspNetCore.StaticFiles取用:

Install-PackageMicrosoft.AspNetCore.StaticFiles

③ 如果我們的檔案伺服器需要能訪問和瀏覽E盤的所有檔案與檔案夾,那麼我們就需要用到 UseStaticFiles和 UseDirectoryBrowser 方法了,在 Startup.Configure 方法下新增如下程式碼:

public void Configure(IApplicationBuilder app){
    FileExtensionContentTypeProvider provider = new FileExtensionContentTypeProvider();
    provider.Mappings[".log"] = "text/plain";
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(@"E:\"),  // 指定靜態檔案目錄
        ServeUnknownFileTypes = true,
        ContentTypeProvider = provider,
        DefaultContentType = "application/x-msdownload", // 設定未識別的MIME型別一個預設z值
    });

    app.UseDirectoryBrowser(new DirectoryBrowserOptions()
    {
        FileProvider = new PhysicalFileProvider(@"E:\"), // 制定目錄,這裡指定 E盤,也可以是其他目錄
    });
}

然後執行程式,這裡選擇使用 Kestrel,訪問:http://:5000/,如下圖所示:

這樣我們就能透過客戶端瀏覽伺服器E盤的所有檔案及檔案夾了。我們還手動設定了未識別的 MIME 型別一個預設值(”application/x-msdownload”),當瀏覽器開啟這些未識別型別的檔案,就會下載這些檔案。像 .log 這樣的檔案就被手動設定為文字方式,瀏覽器會直接展示出來。這樣我們也就實現了一個簡單的檔案伺服器。

如果想用區域網內其他電腦或手機檢視圖片或影片檔案,則修改Properties檔案下 launchSettings.json 配置檔案中的應用程式URL就可以實現:

"WebApplication": {
  "commandName": "Project",
  "launchBrowser": true,
  "applicationUrl": "https://*:5001;http://*:5000",  // 這樣就可以透過 http:ip:5000訪問
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
}

這樣在同一區域網內,在手機上訪問 http:ip:5000,就能訪問伺服器E盤中的檔案了。


參考原文

Microsoft 檔案 ASP.NET Core 中介軟體
ASP.NET Core 中介軟體(Middleware)詳解

原文地址:https://www.cnblogs.com/anayigeren/p/10282441.html

贊(0)

分享創造快樂