ASP.NET Core 6框架揭秘實例演示[29]:搭建文件服務器

通過HTTP請求獲取的Web資源很多都來源于存儲在服務器磁盤上的靜態文件。對于ASP.NET應用來說,如果將靜態文件存儲到約定的目錄下,絕大部分文件類型都是可以通過Web的形式對外發布的。“Microsoft.AspNetCore.StaticFiles” 這個NuGet包中提供了三個用來處理靜態文件請求的中間件,我們可以用它們搭建一個文件服務器。[本文節選《ASP.NET Core 6框架揭秘》第18章]

[1901]以Web形式發布文件(圖片)(源代碼)
[1902]以Web形式發布文件(PDF)(源代碼)
[1903]顯式文件目錄結構(源代碼)
[1904]顯示目錄的默認頁面(源代碼)
[1905]定制目錄的默認頁面(源代碼)
[1906]設置默認的媒體類型(源代碼)
[1907]映射文件擴展名的媒體類型(源代碼)

[1901]以Web形式發布文件(圖片)

作為演示實例是ASP.NET應用具有如圖1所示的項目結構。在默認作為WebRoot的“wwwroot”目錄下,我們將JavaScript腳本文件、CSS樣式文件和圖片文件存放到對應的子目錄(js、css和img)下。該目錄下的所有文件將自動發布為Web資源,客戶端可以訪問相應的URL來讀取對應它們的內容。

6dfee9d533214c42a1db3fc1134c4d5a.png

圖1 靜態文件發布的項目結構

針對具體某個靜態文件的請求是通過StaticFileMiddleware中間件來處理。如下所示的演示程序中調用IApplicationBuilder接口的UseStaticFiles擴展方法注冊的就是這個中間件。

var?app?=?WebApplication.Create();
app.UseStaticFiles();
app.Run();

演示程序運行之后,就可以通過GET請求的方式來讀取對應文件的內容,目標文件相對于WebRoot目錄的路徑就是對應URL的路徑,如JPG圖片文件“~/wwwroot/img/dolphin1.jpg”對應的URL路徑為“/img/dolphin1.jpg”。如果直接利用瀏覽器訪問這個URL,目標圖片就會直接以圖2所示的形式顯示出來。

5b0c3cacb8a04803a36a5004257aef1d.png

圖2 以Web形式請求發布的圖片文件

[1902]以Web形式發布文件(PDF)

上面通過一個簡單的實例將WebRoot所在目錄下的所有靜態文件發布為Web資源,如果需要發布的靜態文件存儲在其他目錄下呢?比如我們將上面演示的應用程序的一些文檔存儲在圖3所示的“~/doc/”目錄下,那么對應的程序又該如何編寫呢?

c12683775982e7f535d189b75d71213f.png

圖3 發布“~/doc/”和“~/wwwroot”目錄下的文件

ASP.NET應用在大部分情況下都是利用一個IFileProvider對象來讀取文件的,針對靜態文件的讀取請求處理也不例外。StaticFileMiddleware中間件內部維護著一個IFileProvider對象和請求路徑的映射關系。如果調用UseStaticFiles方法沒有指定任何參數,那么這個映射的路徑就是應用的基地址(PathBase),采用的IFileProvider對象就是指向WebRoot目錄的PhysicalFileProvider對象。上述需求可以通過定制這個映射關系來實現。如下面的代碼片段所示,我們在現有程序的基礎上額外添加了一次針對UseStaticFiles擴展方法的調用,并利用作為參數的StaticFileOptions配置選項添加請求路徑(“/documents”)與對應IFileProvider對象(針對路徑“~/doc/”的PhysicalFileProvider對象)之間的映射關系。

using?Microsoft.Extensions.FileProviders;var?path?=?Path.Combine(Directory.GetCurrentDirectory(),?"doc");
var?options?=?new?StaticFileOptions
{FileProvider?=?new?PhysicalFileProvider(path),RequestPath?=?"/documents"
};var?app?=?WebApplication.Create();
app.UseStaticFiles().UseStaticFiles(options);
app.Run();

按照上面這段程序指定的映射關系,對于存儲在“~/doc/”目錄下的這個PDF文件(checklist.pdf),請求URL采用的路徑就應該是“/documents/checklist.pdf”。如果利用瀏覽器請求這個地址時,PDF文件的內容就會按照圖4所示的形式顯示在瀏覽器上。

064f0b6773cc1de6ce456145482a2f44.png

圖4 以Web形式請求發布的PDF文件

[1903]顯示文件目錄結構

StaticFileMiddleware中間件只會處理針對具體的某個靜態文件的請求,如果利用瀏覽器發送一個針對目錄路徑的請求(比如“/img”),我們將得到狀態為“404 Not Found”的響應。如果希望瀏覽器呈現出目標目錄的結構,就可以注冊DirectoryBrowserMiddleware中間件。這個中間件會返回一個HTML頁面,請求目錄下的結構會以表格的形式顯示在這個頁面中。我們演示的程序按照如下方式調用IApplicationBuilder接口的UseDirectoryBrowser擴展方法注冊了這個中間件。

using?Microsoft.Extensions.FileProviders;var?path?=?Path.Combine(Directory.GetCurrentDirectory(),?"doc");
var?fileProvider?=?new?PhysicalFileProvider(path);var?fileOptions?=?new?StaticFileOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};var?diretoryOptions?=?new?DirectoryBrowserOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};var?app?=?WebApplication.Create();
app.UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser()?.UseDirectoryBrowser(diretoryOptions);
app.Run();

當上面的應用啟動之后,如果利用瀏覽器向針對某個目錄的URL(如“/”或者“/img”)發起請求,目標目錄的內容(包括子目錄和文件)就會以圖5所示的形式顯示在一個表格中。可以看出在呈現的表格中,當前目錄的子目錄和文件均會顯示為鏈接。

ea92121c0b614442ed39ad26c6e1d630.png

圖5 顯示目錄內容

[1904]顯示目錄的默認頁面

UseDirectoryBrowser中間件會將整個目標目錄的結構和所有文件全部暴露出來,所以這個中間件需要根據自身的安全策略謹慎使用。對于針對目錄的請求,更加常用的處理策略就是顯示一個保存該目錄下的默認頁面。默認頁面文件一般采用如下四種命名約定(default.htm、default.html、index.htm和index.html)。默認頁面的呈現實現DefaultFilesMiddleware中間件中,我們演示的這個應用可以按照如下方式調用IApplicationBuilder接口的UseDefaultFiles擴展方法來注冊這個中間件。

using?Microsoft.Extensions.FileProviders;var?path?=?Path.Combine(Directory.GetCurrentDirectory(),?"doc");
var?fileProvider?=?new?PhysicalFileProvider(path);var?fileOptions?=?new?StaticFileOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};
var?diretoryOptions?=?new?DirectoryBrowserOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};
var?defaultOptions?=?new?DefaultFilesOptions
{RequestPath?=?"/documents",FileProvider?=?fileProvider,
};var?app?=?WebApplication.Create();
app???.UseDefaultFiles()?.UseDefaultFiles(defaultOptions).UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser().UseDirectoryBrowser(diretoryOptions);app.Run();

下面在“~/wwwroot/img/”和“~/doc”目錄下分別創建一個名為index.html的默認頁面,并且在該.html文件的主體部分指定一段簡短的文字(This is an index page!)。我們在應用啟動之后利用瀏覽器訪問這兩個目錄(“/img”和“/documents”),默認頁面就會以圖6的形式顯示出來。

a402891898e451ee040e5c47ca2f189f.png

圖6 顯示默認頁面

[1905]定制目錄的默認頁面

我們須將DefaultFilesMiddleware中間件放在StaticFileMiddleware和DirectoryBrowserMiddleware中間件之前。這是因為DirectoryBrowserMiddleware和DefaultFilesMiddleware中間件處理的均是針對目錄的請求,如果先注冊DirectoryBrowserMiddleware中間件,那么顯示的總是目錄的結構。如果先注冊用于顯示默認頁面的DefaultFilesMiddleware中間件,那么在默認頁面不存在的情況下它會將請求分發給后續中間件,此時DirectoryBrowserMiddleware中間件將當前目錄的結構呈現出來。要先于StaticFileMiddleware中間件之前注冊DefaultFilesMiddleware中間件是因為后者是通過采用URL重寫的方式實現的。這個中間件會將針對目錄的請求改寫成針對默認頁面的請求,而最終針對默認頁面的請求還需要依賴StaticFileMiddleware中間件來完成。

2e79308b7778b5ebfaca753819b37767.png

圖7 重命名默認頁面

DefaultFilesMiddleware中間件在默認情況下總是以約定的名稱在當前請求的目錄下定位默認頁面。如果作為默認頁面的文件沒有采用這樣的約定命名,比如我們如圖7所示的方式將默認頁面命名為readme.html,就需要按照如下方式顯式指定默認頁面的文件名(S1905)。

using?Microsoft.Extensions.FileProviders;var?path?=?Path.Combine(Directory.GetCurrentDirectory(),?"doc");
var?fileProvider?=?new?PhysicalFileProvider(path);
var?fileOptions?=?new?StaticFileOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};
var?diretoryOptions?=?new?DirectoryBrowserOptions
{FileProvider?=?fileProvider,RequestPath?=?"/documents"
};
var?defaultOptions1?=?new?DefaultFilesOptions();
var?defaultOptions2?=?new?DefaultFilesOptions
{RequestPath?=?"/documents",FileProvider?=?fileProvider,
};defaultOptions1.DefaultFileNames.Add("readme.html");?
defaultOptions2.DefaultFileNames.Add("readme.html");
var?app?=?WebApplication.Create();
app.UseDefaultFiles(defaultOptions1)?.UseDefaultFiles(defaultOptions2).UseStaticFiles().UseStaticFiles(fileOptions).UseDirectoryBrowser().UseDirectoryBrowser(diretoryOptions);app.Run();

[1906]設置默認的媒體類型

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

StaticFileMiddleware中間件針對媒體類型的解析是通過一個IContentTypeProvider對象來完成的, FileExtensionContentTypeProvider是對該接口的默認實現。FileExtensionContentTypeProvider根據文件的擴展命名來解析媒體類型。它在內部預定了數百種常用文件擴展名與對應媒體類型之間的映射關系,所以如果發布的靜態文件具有標準的擴展名,StaticFileMiddleware中間件就能為對應的響應賦予正確的媒體類型。

4d91eab6eff9554663b0e60f6fe51f61.png

圖8 重命名默認頁面

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

var?options?=?new?StaticFileOptions
{ServeUnknownFileTypes?=?true,DefaultContentType?=?"image/jpg"
};
var?app?=?WebApplication.Create();
app.UseStaticFiles(options);app.Run();

[1907]映射文件擴展名的媒體類型

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

using?Microsoft.AspNetCore.StaticFiles;var?contentTypeProvider?=?new?FileExtensionContentTypeProvider();
contentTypeProvider.Mappings.Add(".img",?"image/jpg");
var?options?=?new?StaticFileOptions
{ContentTypeProvider?=?contentTypeProvider
};var?app?=?WebApplication.Create();
app.UseStaticFiles(options);app.Run();

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281671.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281671.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281671.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

js 棧(進制轉換)

<!DOCTYPE html>Documentposted 2017-12-07 19:33 mysure 閱讀(...) 評論(...) 編輯 收藏 刷新評論刷新頁面返回頂部轉載于:https://www.cnblogs.com/ar13/p/8000718.html

流程展示 php,js實現動態的流程進度展示條

這次給大家帶來js實現動態的流程進度展示條&#xff0c;js實現動態流程進度展示條的注意事項有哪些&#xff0c;下面就是實戰案例&#xff0c;一起來看一下。一、設計思路分為以下幾步(僅供參考)【豎線線】這個采用ul的list標簽制作&#xff0c;保證了可隨時添加&#xff0c;以…

【我們一起寫框架】C#的AOP框架

原文:【我們一起寫框架】C#的AOP框架前言 AOP&#xff0c;大家都是聽過的&#xff0c;它是一種面向切面的設計模式。 不過AOP雖然是被稱為設計模式&#xff0c;但我們應該很少能看到AOP設計的框架。為什么呢&#xff1f; 因為&#xff0c;AOP單獨設計的框架幾乎是無法使用的。普…

新浪微博授權認證過程

為什么80%的碼農都做不了架構師&#xff1f;>>> 一、授權認證 1、請求用戶授權Token URL&#xff1a; https://api.weibo.com/oauth2/authorize HTTP請求方式:GET/POST 請求參數 必選 類型及范圍 說明 client_id true string 申請應用時分配的AppKey。 redire…

VisualStudio 使用 FastTunnel 輔助搭建遠程調試環境

有時候需要遠程調試一些用戶問題&#xff0c;期望能使用本機的 Visual Studio 開發環境&#xff0c;調試遠程的用戶的設備上的應用。這時會遇到的一個問題是如何讓本機的 Visual Studio 可以連接上遠程的用戶的設備&#xff0c;從而進行調試。本文將告訴大家如何采用 FastTunne…

深入理解null的原理

--null的原理 --oracle一直將null和空字符串’’<長度為0>同等對待<如’’ is null是true,’’null為false,如果聲明a varchar2:’’,那么a is null為true,a’’為false>--1.null的運算 --算術表達式和null 運算總為null,實際上所有的操作符除了||連接操作符外&…

阻止中文輸入法輸入拼音的時候觸發input事件

阻止中文輸入法輸入拼音的時候觸發input事件 前言 最近看element-ui源碼的時候看到el-input發現的。這個少見的事件。 compositionstart、compositionend事件&#xff08;MDN解釋) compositionstart事件觸發于一段文字的輸入之前&#xff08;類似于 keydown 事件&#xff0c;但…

Python1

python介紹python是一種解釋型的&#xff0c;面對對象的。帶有動態語義的高級程序設計語言python簡史1989年,Guido(龜叔)為ABC 語言寫的一個插件。因Monty Python的喜劇團體的原因,故給這個語言起名為python。linux也是1989年誕生的,1991年正式發布linux1.0內核;1990年, 發布py…

ncut算法matlab實現,ncut_multiscale_1_6 經典的圖像分割算法 的Matlab代碼。 238萬源代碼下載- www.pudn.com...

文件名稱: ncut_multiscale_1_6下載收藏√ [5 4 3 2 1 ]開發工具: matlab文件大小: 587 KB上傳時間: 2015-04-17下載次數: 4提 供 者: HH詳細說明&#xff1a;經典的圖像分割算法NCut的Matlab代碼。-Matlab code of classic image segmentation algorithm NCut .文件列表(…

使用.NET從零實現基于用戶角色的訪問權限控制

使用.NET從零實現基于用戶角色的訪問權限控制本文將介紹如何實現一個基于.NET RBAC 權限管理系統&#xff0c;如果您不想了解原理&#xff0c;可查看推送的另一篇文章關于Sang.AspNetCore.RoleBasedAuthorization[1] 庫是使用介紹&#xff0c;直接使用該庫即可。背景在設計系統…

數據歸一化

數據歸一化 數據的標準化是將數據按比例縮放&#xff0c;使之落入一個小的特定區間&#xff0c;一般為0到1之間。在某些比較和評價的指標處理中經常會用到&#xff0c;去除數據的單位限制&#xff0c;將其轉化為無量綱的純數值&#xff0c;便于不同單位或量級的指標能夠進行比較…

vi is failed with error E382: Cannot write, 'buftype' option is set in Linux

在linux下生成jar文件遇到了編碼問題&#xff0c;于是想vi t.jar&#xff0c;在保存是報錯&#xff1a;E382: Cannot write, buftype option is set 解決方法&#xff1a; 可以用下面的命名查看buftype的設置&#xff0c;當buftypenofile時&#xff0c;不能保存文件&#xff0c…

列表生成式的使用

輸入&#xff1a;[Hello, World, 18, Apple, None] 輸出&#xff1a;[hello, world, apple] L [Hello, World, 18, Apple, None] print([w.lower() for w in L if isinstance(w, str)])# -- coding: utf-8 -- L [Hello, World, 18, Apple, None] L2 [] L2 [w.lower() for w…

matlab 12位 顯示不出來,求助大神,為何不同機器運行MATLAB結果不同

求助&#xff1a;不同機器運行MATLAB結果不同我調用MATLAB優化工具箱的庫函數fmincon&#xff0c;使用相同的初始解(可行解)&#xff0c;對同一個問題進行局部搜索(算法為序列二次規劃&#xff0c;即SQP)&#xff0c;但在不同機器上得到的結果不同。一共有五臺機器 (為了方便&a…

.NET性能系列文章一:.NET7的性能改進

這些方法在.NET7 中變得更快照片來自 CHUTTERSNAP[1] 的 Unsplash[2]歡迎閱讀.NET 性能系列的第一章。這一系列的特點是對.NET 世界中許多不同的主題進行研究、比較性能。正如標題所說的那樣&#xff0c;本章節在于.NET7 中的性能改進。你將看到哪種方法是實現特定功能最快的方…

UVA - 10061 How many zero#39;s and how many digits ?

n!x*b^y, 當x為正整數時,最大的y就是n!末尾0的個數了, 把n,b分別拆成素因子相乘的形式: 比如, n5,b16 n5,b2^4, 非常明顯,末尾0的個數為0 10進制時,n!a*10^x b進制時,n!c*b^y 非常明顯,n!的位數就是最大的x1 這里計算我用了log,精度設置為1e-9 #include<iostream> #inclu…

丁洪波 -- 不要“ 總是拿著微不足道的成就來騙自己”

都市快報實盤大賽25期&#xff1a;于海飛/丁洪波榮獲冠亞軍 七禾網 時間&#xff1a;2010-11-02 12:47:05 來源&#xff1a;期貨中國10月30日下午&#xff0c;2010年浙商期貨實盤大賽第三季度&#xff08;都市快報實盤大賽第25期&#xff09;頒獎典禮在天科大廈浙商期貨大會議室…

面試專題(Mysql及Mongodb)

2019獨角獸企業重金招聘Python工程師標準>>> mysql面試題 1. 各個數據庫存儲引擎區別 mysql的存儲引擎是針對表進行設置的&#xff0c;一個庫的不同表可以設置不同的存儲引擎&#xff0c;mysql默認支持多種存儲引擎&#xff0c;以適用不同領域的數據庫應用需要&…

織夢網站翻頁php,dedecms織夢網站列表頁和內容頁分頁樣式

織夢分頁標簽{dede:pagelist istitem"index,pre,next,end,option,info," listsize"5"/}&#xff0c;{dede:prenext getpre/}&#xff0c;{dede:prenext getnext/}。默認樣式和使用模板css樣式布局不一樣,這時又不想重寫樣式&#xff0c;我們可以修改織夢標…

通過中間件添加用戶的Claim

本文主要介紹 Sang.AspNetCore.RoleBasedAuthorization[1] 庫如何通過中間件實現對用戶 Claim 的添加。背景前面我們介紹了通過對自定義授權策略和自定義授權處理程序的使用實現了基本的RBAC權限設計&#xff0c;將大量的用戶可訪問資源及操作的標識直接放到用戶的 JWT Token 中…